Swift: структура Hashable со свойством словаря
У меня есть структура в 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, который требует, чтобы MapKey соответствовал протоколу Hashable.
Какова была бы правильная реализация Hashable для такой структуры?
extension MapKey: Hashable {
var hashValue: Int {
return ??? // values does not have a hash function/property.
}
}
Я занимался некоторыми исследованиями, но не смог определить, какой правильный способ хешировать словарь, поскольку мне нужно иметь возможность генерировать значение хеша для самого свойства values. Любая помощь очень ценится.
Ответы
Ответ 1
Я думаю, вам нужно просмотреть свою модель данных, если вам нужно использовать целую структуру в качестве словарного ключа. Во всяком случае, здесь один из способов сделать это:
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
.
Ответ 2
Так как оба id и значения неизменяемы, оба могут использоваться в качестве основы для 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
}