繁体   English   中英

斯卡拉的詹金斯·哈希

[英]Jenkins Hash in Scala

我正在尝试在Scala中编写Jenkins Hash( http://burtleburtle.net/bob/hash/doobs.html )。 这有点棘手...

   switch(len)              /* all the case statements fall through */
   {
   case 11: c+=((ub4)k[10]<<24);
   case 10: c+=((ub4)k[9]<<16);
   case 9 : c+=((ub4)k[8]<<8);
      /* the first byte of c is reserved for the length */
   case 8 : b+=((ub4)k[7]<<24);
   case 7 : b+=((ub4)k[6]<<16);
   case 6 : b+=((ub4)k[5]<<8);
   case 5 : b+=k[4];
   case 4 : a+=((ub4)k[3]<<24);
   case 3 : a+=((ub4)k[2]<<16);
   case 2 : a+=((ub4)k[1]<<8);
   case 1 : a+=k[0];
     /* case 0: nothing left to add */
   }   

match语句不会落在Scala中(这是一个很好的设计决策)。 所以我能想到的最好的方法是每个案例有一个if语句。 我希望有人能看到更精巧的解决方案……

大概是这样吗?

        val (a,b,c) = k
            .zipWithIndex
            .foldLeft((0,0,0)) { case ((a,b,c), (v, index)) => 
                index match {
                 case i if i < 4 => (a + (v << i*8), b, c)
                 case i if i < 8 => (a, b + (v << (i-4)*8), b, c)
                 case i => (a, b, c + (v << (i-7)*8))
                }
            }

我尚未测试结果,但这是实现它的一种方法。 删除并获取每个值所需的数组字节。 同时从右折叠以将最右边的值从0旋转到8到16到24。

在JVM中使用unsigned有点麻烦,并且要求我们将其转换为更宽的数据类型(即,将字节转换为int,将int转换为long)。 因此,我们使用longify将字节转换为long。 我们还需要考虑一半的字节值为负。

val longify = ((n: Byte) => n.toLong) andThen (n => if (n < 0) n + 256 else n)
def sum(m: Int, n: Int) = 
    k.drop(m).take(n).foldRight(0L)((b, s) => longify(b) + (s << 8))
val a = sum(0, 4)
val b = sum(4, 4)
val c = (sum(9, 3) << 8) + k.size

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM