Почему struct должна соответствовать Hashable, а также универсальному массиву при преобразовании в словарь
Цель состояла в том, чтобы преобразовать элементы в общем списке в словарь для переменной uniqueKeys
, но я увидел ошибку:
Невозможно указать значение неверного или неоднозначного типа
Я знал что-то необходимое для соответствия Hashable
протокол и в конечном итоге приземлился на решение, но я не совсем понимаю, почему это решение работает.
- Я понимаю почему
T
должно бытьHashable
так как это 'входит в словарный ключ, но почему такжеCustomSet
? - Если
CustomSet
использованияHashable
почему мне не нужно ничего писать в его расширении?
исходный код
struct CustomSet<T : Comparable > {
private var list: [T]
init(_ list: [T]){
let uniqueKeys = list.reduce(into: [:]){ dict, item in
dict[item, default: 0] += 1
}.keys
self.list = Array(uniqueKeys)
}
}
extension CustomSet : Equatable {
static func == (lhs: CustomSet, rhs: CustomSet) -> Bool {
return lhs.list.count == rhs.list.count && lhs.list.sorted() == rhs.list.sorted()
}
}
Я наконец решил это с:
struct CustomSet<T : Comparable > : Hashable where T : Hashable {
private var list: [T]
init(_ list: [T]){
let uniqueKeys = list.reduce(into: [:]){ dict, item in
dict[item, default: 0] += 1
}.keys
self.list = Array(uniqueKeys)
}
}
extension CustomSet : Equatable {
static func == (lhs: CustomSet, rhs: CustomSet) -> Bool {
return lhs.list.count == rhs.list.count && lhs.list.sorted() == rhs.list.sorted()
}
}
Я также заметил, что факторинг в расширение: extension CustomSet: Hashable where T : Hashable
не похоже на то, что struct CustomSet<T : Comparable > : Hashable where T : Hashable
с точки зрения добавления протокола Hashable, потому что я все еще вижу эту ошибку
Что я пробовал
Если я добавлю это к универсальному типу T
Я все еще видел ту же ошибку.
struct CustomSet<T : Comparable, Hashable >
Если я добавлю Hashable
в CustomSet
Я вижу ошибку
Невозможно преобразовать значение типа '[T]' в ожидаемый тип аргумента 'UnsafeRawBufferPointer'
а также
Наследование от внепротокольного типа 'Hashable'
extension CustomSet : Equatable, Hashable {
static func == (lhs: CustomSet, rhs: CustomSet) -> Bool {
return lhs.list.count == rhs.list.count && lhs.list.sorted() == rhs.list.sorted()
}
func hash(into hasher: inout Hasher) {
var hashValue: Int {
var hasher = Hasher()
self.hash(into: &hasher)
return hasher.finalize()
}
}
}
1 ответ
Там нет необходимости делать CustomSet
соответствовать Hashable
, Просто добавив Hashable
ограничение параметра универсального типа решает ошибку
Невозможно указать значение неверного или неоднозначного типа
, что ожидается, так как Dictionary
Ключи должны соответствовать Hashable
,
Кстати, синтаксис объявления соответствия нескольким протоколам &
не ,
, так что нет необходимости в предложении where.
struct CustomSet<T : Comparable & Hashable> {
private var list: [T]
init(_ list: [T]){
let uniqueKeys = list.reduce(into: [:]){ dict, item in
dict[item, default: 0] += 1
}.keys
self.list = Array(uniqueKeys)
}
}
extension CustomSet : Equatable {
static func == (lhs: CustomSet, rhs: CustomSet) -> Bool {
return lhs.list.count == rhs.list.count && lhs.list.sorted() == rhs.list.sorted()
}
}
Более того, вы можете просто сделать self.list = Array(Set(list))
в инициализаторе, чтобы хранить только уникальные элементы из ввода в вашем list
нет необходимости возиться с Dictionary
,