【问题标题】:Conforming an array of enums to Hashable for use as dictionary key使枚举数组符合 Hashable 以用作字典键
【发布时间】:2016-06-01 12:52:33
【问题描述】:

我想使用自定义枚举数组作为字典键,但我很难弄清楚如何使数组符合 Hashable。编译器告诉我 [Symbol] 不符合 Hashable。我需要做什么才能编译它?

我弄乱了 Array where Element:Symbol 的扩展,但我不知道如何以这种方式添加协议。

enum Symbol:Hashable, Equatable {
    case Dot
    case Dash

    var value:Int {
        get {
            switch self {
            case .Dot:          return 0
            case .Dash:         return 1
        }
    }

    var hashValue:Int {
        return self.value
    }  
}

func ==(left: Symbol, right: Symbol) -> Bool {
    return left.value == right.value
}

struct MorseDictionary {
    static let symbolToStringDictionary:[[Symbol]:String] = [
        [.Dot, .Dash]:"A"
    ]
}

【问题讨论】:

  • 您的最终目标是什么 - 使用数组作为键有什么好处?
  • 想出一个简单的解决方法可能会减少工作量 - 你有一个很好的观点。但作为一个有趣的问题,我仍然想看看我是否可以找到一种方法来使用数组。

标签: ios arrays swift dictionary enums


【解决方案1】:

在 Swift 2.2 中,您不能创建仅限于特定类型数组的扩展

因此,您不能将Symbol 的数组与HashableEquatable 保持一致。 这意味着您不能将符号数组用作字典中的键。

当然,您可以创建一个扩展来制作 Array (every array!!) EquatableHashable,但这是一种疯狂的方法,因为显然您永远无法提供有效的实现。

但是您可以采用另一种方法

首先你的枚举可以这样重写

enum Symbol: Int {
    case Dot = 0, Dash
}

接下来你需要一个符号数组的包装器

struct Symbols: Hashable, Equatable {
    let value: [Symbol]

    // you can use a better logic here
    var hashValue: Int { return value.first?.hashValue ?? 0 }
}

func ==(left: Symbols, right:Symbols) -> Bool {
    return !zip(left.value, right.value).contains { $0.0 != $0.1 }
}

现在你可以创建你的字典了

let dict: [Symbols:String] = [Symbols(value: [.Dot, .Dash]) : "A"]

【讨论】:

  • 包装器是我缺少的技巧!我创建了一个具有符号数组的 Letter 结构。像魅力一样工作,感谢您的提示!
【解决方案2】:

我对@appzYourLife 有同样的想法。所以不要接受我的回答。值得一提的是,我已经为 Symbols 实现了哈希函数。

func ==(left: Symbols, right: Symbols) -> Bool {
    return left.value == right.value
}

enum Symbol: Int {

    case Dot = 0
    case Dash = 1
    case Count = 2
}


struct Symbols: Hashable {

    let symbols: [Symbol]

    init(symbols: [Symbol]) {
        self.symbols = symbols
    }

    var value: Int {

        var sum = 0
        var i = 1

        symbols.forEach({ (s) in

            sum += s.rawValue * i
            i = i * Symbol.Count.rawValue
        })
        return sum
    }

    var hashValue: Int {

        return value % Int(pow(Double(2), Double(Symbol.Count.rawValue)))
    }

}

struct MorseDictionary {

    static let symbolToStringDictionary: [Symbols: String] = [
        Symbols(symbols: [.Dot, .Dash]): "A",
        Symbols(symbols: [.Dash, .Dot]): "B",
        Symbols(symbols: [.Dash, .Dash]): "C",
        Symbols(symbols: [.Dot, .Dot]): "D",
    ]
}

客户代码:

MorseDictionary.symbolToStringDictionary[Symbols(symbols: [.Dot, .Dash])]
MorseDictionary.symbolToStringDictionary[Symbols(symbols: [.Dash, .Dot])]
MorseDictionary.symbolToStringDictionary[Symbols(symbols: [.Dash, .Dash])]
MorseDictionary.symbolToStringDictionary[Symbols(symbols: [.Dot, .Dot])]

结果:

"A"
"B"
"C"
"D"

【讨论】:

  • 感谢您提供详细的代码,感谢您的 appzYourLife,我现在可以正常工作了。符号包装器是最后一块拼图。
猜你喜欢
  • 2014-08-25
  • 2019-06-29
  • 1970-01-01
  • 1970-01-01
  • 2019-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多