Цель состояла в том, чтобы преобразовать элементы общего списка в словарь для переменной 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()
}
}
}
CustomSet
не обязательно должно бытьHashable
, ваш код прекрасно компилируется без соответствияHashable
. Кстати, какой смысл сокращать список доDictionary
, чьи ключи являются элементами списка, если тогда вы просто назначаете ключи указанного словаряlist
? На самом деле вы не уникальные эти ключи. - person Dávid Pásztor   schedule 08.01.2019removeDuplicates
- person Turnipdabeets   schedule 08.01.2019struct CustomSet<T : Comparable & Hashable >
компилирует исходный код. - person Martin R   schedule 08.01.2019struct CustomSet<T : Comparable, Hashable >
, мне просто не хватало&
вstruct CustomSet<T : Comparable & Hashable >
. - person Turnipdabeets   schedule 08.01.2019lhs.list.count == rhs.list.count
. Если структура неизменна, вы можете выполнить сортировку в инициализаторе. - person Sulthan   schedule 08.01.2019func hash(into hasher: inout Hasher)
ничего не делает (кроме объявления неиспользуемого вычисляемого свойства). - person Martin R   schedule 08.01.2019