Swift 应该使用字符串散列来索引持久数据?
Swift String hash should be used to index persistent data?
我偶然发现了我(相对)旧代码中的一个错误,并发现字符串哈希 属性 被证明不是密集唯一的:许多不同的字符串具有相同的哈希值。
参考文档,我只找到"An unsigned integer that can be used as a hash table address",根本没有任何信息。
我的代码片段简单如下:
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 解决这个问题?我应该提供自己的哈希码吗?
我暂时用我的应用程序中的自定义功能替换了原生 String.hash。这解决了问题,具有更好的表观分布:
public func hash(_ string: String) -> Int {
func djb(_ string: String) -> Int {
return string.utf8
.map {return [=10=]}
.reduce(5381) {
([=10=] << 5) &+ [=10=] &+ Int()
}
}
return djb(string)
}
注意:djb hash func 可以在我有时间进行分发时随时更换。
Swift 4
extension String {
var persistantHash: Int {
return self.utf8.reduce(5381) {
([=10=] << 5) &+ [=10=] &+ Int()
}
}
}
用法示例:
"my-string".persistantHash
我偶然发现了我(相对)旧代码中的一个错误,并发现字符串哈希 属性 被证明不是密集唯一的:许多不同的字符串具有相同的哈希值。
参考文档,我只找到"An unsigned integer that can be used as a hash table address",根本没有任何信息。
我的代码片段简单如下:
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 解决这个问题?我应该提供自己的哈希码吗?
我暂时用我的应用程序中的自定义功能替换了原生 String.hash。这解决了问题,具有更好的表观分布:
public func hash(_ string: String) -> Int {
func djb(_ string: String) -> Int {
return string.utf8
.map {return [=10=]}
.reduce(5381) {
([=10=] << 5) &+ [=10=] &+ Int()
}
}
return djb(string)
}
注意:djb hash func 可以在我有时间进行分发时随时更换。
Swift 4
extension String {
var persistantHash: Int {
return self.utf8.reduce(5381) {
([=10=] << 5) &+ [=10=] &+ Int()
}
}
}
用法示例:
"my-string".persistantHash