Swift:带字典的可哈希结构 属性
Swift: Hashable struct with dictionary property
我在 Swift 中有一个结构如下所示:
internal struct MapKey {
internal let id: String
internal let values: [String:String]
}
extension MapKey: Equatable {}
func ==(lhs: MapKey, rhs: MapKey) -> Bool {
return lhs.id == rhs.id && lhs.values == rhs.values
}
我现在有使用MapKey作为Swift字典中key的需求,需要MapKey符合Hashable协议
对于像这样的结构,Hashable 的正确实现应该是什么?
extension MapKey: Hashable {
var hashValue: Int {
return ??? // values does not have a hash function/property.
}
}
我一直在做一些研究,但未能确定对字典进行哈希处理的正确方法是什么,因为我需要能够为 values属性 本身。非常感谢任何帮助。
如果必须使用整个结构作为字典键,我认为您需要检查数据模型。无论如何,这是一种方法:
internal struct MapKey: Hashable {
internal let id: String
internal let values: [String:String]
var hashValue: Int {
get {
var hashString = self.id + ";"
for key in values.keys.sort() {
hashString += key + ";" + values[key]!
}
return hashString.hashValue
}
}
}
func ==(lhs: MapKey, rhs: MapKey) -> Bool {
return lhs.id == rhs.id && lhs.values == rhs.values
}
这假定您在 id
或 values
的键和值中没有分号 (;
)。 Hasable
意味着 Equatable
所以你不需要再次声明它符合 Equatable
。
由于 id 和 values 都是不可变的,都可以用作 equals 和 hashValue 的基础。
但是 - 如果 MapKey.id (顾名思义)唯一标识 MapKey (至少在一个字典的上下文中)
那么只使用 MakKey.id 作为 == 运算符和 hashValue
的基础既简单又高效
internal struct MapKey: Hashable {
internal let id: String
internal let values: [String:String]
var hashValue: Int {
get { return self.id.hashValue}
}
}
func ==(lhs: MapKey, rhs: MapKey) -> Bool {
return lhs.id == rhs.id
}
基础数据类型在Swift 4.2中是Hashable的,你只需要让你的MapKey结构符合Hashable协议:
struct MapKey: Hashable {
let id: String
let values: [String: String]
}
如果你想使用 class,你需要像这样符合 hash(:) 函数:
class MapKey: Hashable {
static func == (lhs: MapKey, rhs: MapKey) -> Bool {
return lhs.id == rhs.id && lhs.values == rhs.values
}
let id: String = ""
let values: [String: String] = [:]
func hash(into hasher: inout Hasher) {
hasher.combine(id)
hasher.combine(values)
}
}
我在 Swift 中有一个结构如下所示:
internal struct MapKey {
internal let id: String
internal let values: [String:String]
}
extension MapKey: Equatable {}
func ==(lhs: MapKey, rhs: MapKey) -> Bool {
return lhs.id == rhs.id && lhs.values == rhs.values
}
我现在有使用MapKey作为Swift字典中key的需求,需要MapKey符合Hashable协议
对于像这样的结构,Hashable 的正确实现应该是什么?
extension MapKey: Hashable {
var hashValue: Int {
return ??? // values does not have a hash function/property.
}
}
我一直在做一些研究,但未能确定对字典进行哈希处理的正确方法是什么,因为我需要能够为 values属性 本身。非常感谢任何帮助。
如果必须使用整个结构作为字典键,我认为您需要检查数据模型。无论如何,这是一种方法:
internal struct MapKey: Hashable {
internal let id: String
internal let values: [String:String]
var hashValue: Int {
get {
var hashString = self.id + ";"
for key in values.keys.sort() {
hashString += key + ";" + values[key]!
}
return hashString.hashValue
}
}
}
func ==(lhs: MapKey, rhs: MapKey) -> Bool {
return lhs.id == rhs.id && lhs.values == rhs.values
}
这假定您在 id
或 values
的键和值中没有分号 (;
)。 Hasable
意味着 Equatable
所以你不需要再次声明它符合 Equatable
。
由于 id 和 values 都是不可变的,都可以用作 equals 和 hashValue 的基础。 但是 - 如果 MapKey.id (顾名思义)唯一标识 MapKey (至少在一个字典的上下文中) 那么只使用 MakKey.id 作为 == 运算符和 hashValue
的基础既简单又高效 internal struct MapKey: Hashable {
internal let id: String
internal let values: [String:String]
var hashValue: Int {
get { return self.id.hashValue}
}
}
func ==(lhs: MapKey, rhs: MapKey) -> Bool {
return lhs.id == rhs.id
}
基础数据类型在Swift 4.2中是Hashable的,你只需要让你的MapKey结构符合Hashable协议:
struct MapKey: Hashable {
let id: String
let values: [String: String]
}
如果你想使用 class,你需要像这样符合 hash(:) 函数:
class MapKey: Hashable {
static func == (lhs: MapKey, rhs: MapKey) -> Bool {
return lhs.id == rhs.id && lhs.values == rhs.values
}
let id: String = ""
let values: [String: String] = [:]
func hash(into hasher: inout Hasher) {
hasher.combine(id)
hasher.combine(values)
}
}