应该使用Swift String hash来索引持久数据?

时间:2016-08-30 17:58:32

标签: string hash swift3

我偶然发现了我的(相对)旧代码中的一个错误,并发现String散列属性被证明不是密集唯一的:许多不同的字符串具有相同的散列值。

参考文档,我只找到"一个无符号整数,可以用作哈希表地址"它根本没有提供任何信息。

我的代码段如下所示:

func getCacheIndex(sUrl: String) -> Int {
   return sUrl.hash
}

并为给定的不同字符串生成以下内容(标题参数不同,而XXXXXXX表示替换的键字符串):

FileCache hash is -4052854053573130360 for url
 https://maps.googleapis.com/maps/api/streetview?size=675x900&location=46.414382,10.013988&heading=135&pitch=-0.76&key=XXXXXXXXXXXXXXXXXXX 

FileCache hash is -4052854053573130360 for url
 https://maps.googleapis.com/maps/api/streetview?size=675x900&location=46.414382,10.013988&heading=180&pitch=-0.76&key=XXXXXXXXXXXXXXXXXXX

String有一个hashValue,但它清楚地表明我们不应该使用它来保持运行之间的任何东西。

你如何用Swift解决这个问题?我应该提供自己的哈希码吗?

2 个答案:

答案 0 :(得分:2)

我暂时用我的应用程序中的自定义函数替换原生String.hash。这解决了问题,具有更好的明显分布:

public func hash(_ string: String) -> Int {
    func djb(_ string: String) -> Int {

        return string.utf8
            .map {return $0}
            .reduce(5381) {
                ($0 << 5) &+ $0 &+ Int($1)
        }
    }

    return djb(string)
}

注意:只要我有时间处理分发,就可以随时替换djb哈希函数。

答案 1 :(得分:0)

快捷键4

extension String {
    var persistantHash: Int {
        return self.utf8.reduce(5381) {
            ($0 << 5) &+ $0 &+ Int($1)
        }
    }
}

用法示例:

"my-string".persistantHash