为什么struct在转换为字典时需要符合Hashable以及Generic array
Why does struct need to conform to Hashable as well as Generic array when converting to a dictionary
目标是将通用列表中的项目转换为变量 uniqueKeys
的字典,但我看到了错误:
Cannot subscript a value of incorrect or ambiguous type
我知道需要遵守 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
在添加 Hashable 协议方面似乎与 struct CustomSet<T : Comparable > : Hashable where T : Hashable
不一样,因为我仍然看到该错误
我试过的
如果我将它添加到泛型类型 T
,我仍然看到同样的错误。
struct CustomSet<T : Comparable, Hashable >
如果我将 Hashable
添加到 CustomSet
,我会看到错误
Cannot convert value of type '[T]' to expected argument type
'UnsafeRawBufferPointer'
和
Inheritance from non-protocol type '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
限制就解决了错误
Cannot subscript a value of incorrect or ambiguous type
,这是预期的,因为 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
。
目标是将通用列表中的项目转换为变量 uniqueKeys
的字典,但我看到了错误:
Cannot subscript a value of incorrect or ambiguous type
我知道需要遵守 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
在添加 Hashable 协议方面似乎与 struct CustomSet<T : Comparable > : Hashable where T : Hashable
不一样,因为我仍然看到该错误
我试过的
如果我将它添加到泛型类型 T
,我仍然看到同样的错误。
struct CustomSet<T : Comparable, Hashable >
如果我将 Hashable
添加到 CustomSet
,我会看到错误
Cannot convert value of type '[T]' to expected argument type 'UnsafeRawBufferPointer'
和
Inheritance from non-protocol type '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
限制就解决了错误
Cannot subscript a value of incorrect or ambiguous type
,这是预期的,因为 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
。