我有一个“通过String.hashValue
获取字符串的哈希”代码,我在下面添加了它。此代码在Xcode 9.4.1中运行良好。
工作得很好意味着每当我关闭app并重新打开它时,hashValue
的结果是相同的(唯一的)
private func cacheName(of url: String) -> String {
// The url is url of a png image, for example www.imageurl.com/image.png
return "\(url.hashValue)"
}
当我在Xcode 10中构建我的项目时,每次重新启动应用程序时结果都会更改(再次关闭并打开应用程序)。 iOS,设备,Swift版本相同。所以我认为问题是Xcode 10改变了对hashValue
有影响的东西(可能在构建应用程序时配置??)
如果我使用String.hash
代替,它运作良好。但在之前的版本中,我保存了hashValue
结果,所以我不想改变它。
我如何保持String.hashValue
的结果每次都是独一无二的。或任何建议将不胜感激
Swift 4.2实现了SE-0206:Hashable Enhancements。这引入了一个新的Hasher结构,它提供了随机种子散列函数。这就是为什么散列结果每次都不同(因为种子是随机的)。您可以通过生成随机种子here找到Hasher结构的实现。
如果你想要一个与String相关联的稳定哈希值,在设备和app lauches上,你可以使用solution这个Warren Stringer:
let str = "Hello"
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
}
strHash(str) //177798404835661
或者在String上定义these扩展名:
extension String {
var djb2hash: Int {
let unicodeScalars = self.unicodeScalars.map { $0.value }
return unicodeScalars.reduce(5381) {
($0 << 5) &+ $0 &+ Int($1)
}
}
var sdbmhash: Int {
let unicodeScalars = self.unicodeScalars.map { $0.value }
return unicodeScalars.reduce(0) {
(Int($1) &+ ($0 << 6) &+ ($0 << 16)).addingReportingOverflow(-$0).partialValue
}
}
}
"Hello".djb2hash //210676686969
"Hello".sdbmhash //5142962386210502930
(这是在Xcode 10,Swift 4.2上执行的)