为什么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 协议并最终确定了解决方案,但我不完全理解为什么这个解决方案有效。

  1. 我理解为什么 T 需要成为 Hashable 因为它进入字典键,但为什么还要 CustomSet
  2. 如果 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