【问题标题】:Enum as a key for dictionary枚举作为字典的键
【发布时间】:2019-06-14 17:31:17
【问题描述】:

我有一本字典

var observers: [ObservingType: [MessageObserverManager?]] = .init()

我在这里使用枚举作为键,但由于某些原因它不起作用,字典不会使用这些键创建任何对象。

enum ObservingType: Hashable {
case messages(codeId: Int, codeTwoId: Int)
case allMessages
case threadMessages(otherId: Int)

static func == (lhs: ObservingType, rhs: ObservingType) -> Bool {
    return lhs.hashValue == rhs.hashValue
}

func hash(into hasher: inout Hasher) {
    switch self {
    case .messages(let codeId, let codeTwoId):
        hasher.combine(codeId)
        hasher.combine(codeTwoId)
        hasher.combine(1000 / Int.random(in: 1...25))

    case .allMessages:
        hasher.combine(100000 / Int.random(in: 1...25))

    case .threadMessages(let otherId):
        hasher.combine(otherId)
        hasher.combine(100000000 / Int.random(in: 1...25))
    }
}

你不知道枚举有什么问题?

守卫观察者[.allMessages]?.isEmpty ??否则 { 观察者[.allMessages]?.append(观察者)

    return
}

observers[.allMessages] = [observer]

这是我用来添加值的代码,问题是我没有创建那些数组,所以原因不在枚举中,对不起,谢谢帮助!

【问题讨论】:

  • 显示说明字典问题的代码。
  • 那么将随机值混入散列的目的是什么?这绝对违反了相同值必须具有相同哈希的约定。
  • 请注意,==hash(into:) 都可以由编译器自动合成。
  • @Martin R,感谢你们的 cmets,我真的以错误的方式实现了 hashable。我删除了所有,编译器自动合成,但主要原因是我没有创建一个数组,我打算在其中添加对象。再次感谢!

标签: swift dictionary hash enums


【解决方案1】:

您对== 的实现不正确。不要比较哈希值。比较实际值。请记住,允许两个不相等的值具有相同的哈希值。

hash 的实现不应使用随机数。删除这些行。给定值的哈希值需要稳定(至少在应用程序的单次执行期间)。您无法在键的哈希值不断变化的字典中查找值。

在这种情况下,最简单的解决方案是让编译器同时生成==hash(into:)。那么你的代码就变成了:

enum ObservingType: Hashable {
    case messages(codeId: Int, codeTwoId: Int)
    case allMessages
    case threadMessages(otherId: Int)
}

它更简单,您现在可以使用enum 作为字典的键。

【讨论】:

  • 或者去掉这两个实现,让编译器合成它们。
  • @rmaddy 谢谢你,你真的帮了大忙,但主要原因是我没有创建数组并将对象添加到 nil。谢谢!
猜你喜欢
  • 2019-06-29
  • 2018-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多