【问题标题】:Hash value of String that would be stable across iOS releases?跨 iOS 版本稳定的 String 的哈希值?
【发布时间】:2016-03-09 03:03:26
【问题描述】:

在 iOS 的文档 String.hash 中说:

您不应依赖此属性具有相同的哈希值 OS X 版本。

(奇怪为什么他们在 iOS 文档中提到 OS X)

嗯,我需要一个不会随着 iOS 版本而改变的哈希函数。可以很简单,我不需要 SHA 之类的东西。有什么图书馆吗?

关于这个here 还有另一个问题,但那里接受的(也是唯一的)答案只是表明我们应该尊重文档中的注释。

【问题讨论】:

  • 如果它可以简单,为什么不使用MD5 hash编辑:swift version
  • @Fonix 是的,这可能是解决方案。您要链接的问题有很多答案 - 您能否推荐任何在 Swift 中具有稳定和快速 MD5 哈希实现的答案?
  • 请参阅我的第一条评论中的第二个链接,但除此之外,还有大量的解决方案可以通过快速谷歌搜索

标签: ios swift hash nsstring hashcode


【解决方案1】:

这是 Swift 3 的非加密哈希:

 func strHash(_ str: String) -> UInt64 {
    var result = UInt64 (5381)
    let buf = [UInt8](str.utf8)
    for b in buf {
        result = 127 * (result & 0x00ffffffffffffff) + UInt64(b)
    }
    return result
 }

它在某种程度上源自 C++11 constexpr

    constexpr uint64_t str2int(char const *input) {
    return *input                      // test for null terminator
    ? (static_cast<uint64_t>(*input) + // add char to end
       127 * ((str2int(input + 1)      // prime 127 shifts left almost 7 bits
               & 0x00ffffffffffffff))) // mask right 56 bits
    : 5381;                            // start with prime number 5381
}

不幸的是,两者产生的哈希值不同。为此,您需要反转 strHash 中的迭代器顺序:

for b in buf.reversed() {...}

但这会慢 13 倍,有点类似于我从 https://useyourloaf.com/blog/swift-hashable/ 获得的 djb2hash 字符串扩展

这里有一些基准,用于一百万次迭代:

hashValue execution time: 0.147760987281799
strHash execution time:   1.45974600315094
strHashReversed time:    18.7755110263824
djb2hash execution time: 16.0091370344162
sdbmhash crashed

对于 C++,str2Int 大致与 Swift 3 的 hashValue 一样快:

str2int execution time: 0.136421

【讨论】:

  • Warren 的第一个答案作为字符串扩展的计算属性的稍微更精简的版本:[UInt8](utf8).reduce(UInt64(5381)) { 127 * ($0 &amp; 0x00ffffffffffffff) + UInt64($1) }
  • 有没有办法扭转这个操作?从哈希中获取String
  • @Adam 不。大多数哈希会丢失信息。哈希的主要用途是将长值缩短为不与其他缩短值冲突的较短值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-19
  • 1970-01-01
  • 2011-01-07
  • 1970-01-01
  • 1970-01-01
  • 2010-10-20
  • 1970-01-01
相关资源
最近更新 更多