【问题标题】:Copying ENUM hash and raw values into a dictionary将 ENUM 哈希和原始值复制到字典中
【发布时间】:2019-05-03 10:23:52
【问题描述】:

有没有办法将枚举的所有值复制到字典中,而不在任何 FOR 循环中轮询它们?

例如,从这个枚举:

enum FruitPriority: String {
    case PEARS
    case ORANGES
    case APPLES
}

从 ENUM 中调用某个函数,如下所示:

var fruitPriorityArray: [String : Int] = FruitPriority.someFunction()

并得到这个结果(按照哈希值排序)

["PEARS": 0, "ORANGES": 1, "APPLES": 2]

首选只调用一次 ENUM。

谢谢。

【问题讨论】:

  • 一个“关联数组”在 Swift 中被称为 dictionary。字典是键/值对的无序集合。
  • @MartinR 感谢您的及时答复。你说得对。那么,有没有可能做到这一点无序?
  • 你为什么需要它?为什么不直接将原始值更改为 Int 并改用原始值?

标签: swift dictionary enums associative-array


【解决方案1】:
enum FruitPriority: String, CaseIterable {
    case PEARS
    case ORANGES
    case APPLES
}

let result = FruitPriority.allCases.enumerated().reduce([String: Int]()) { dict, fruit in
    var dict = dict
    dict[fruit.element.rawValue] = fruit.offset
    return dict
}

print(result)

结果是:

[“梨”:0,“橙子”:1,“苹果”:2]

对于 Swift 4.1 及更早的版本,CaseIterable 的实现:

#if swift(>=4.2)
#else
public protocol CaseIterable {
    associatedtype AllCases: Collection where AllCases.Element == Self
    static var allCases: AllCases { get }
}
extension CaseIterable where Self: Hashable {
    static var allCases: [Self] {
        return [Self](AnySequence { () -> AnyIterator<Self> in
            var raw = 0
            return AnyIterator {
                let current = withUnsafeBytes(of: &raw) { $0.load(as: Self.self) }
                guard current.hashValue == raw else {
                    return nil
                }
                raw += 1
                return current
            }
        })
    }
}
#endif

CaseIterable 实现的原始post

【讨论】:

  • 谢谢。但很抱歉,我没有提到我无法使用 Swift 4.2,因为我的开发机器卡在 High Sierra 上。 Xcode 10 需要 Mojave。如果没有 CaseIterable 可以做到这一点吗?
  • @iSofia 你可以在更早的版本中实现 CaseIterable
  • 真的!?我不知道。我会试一试。再次感谢维亚切斯拉夫。
  • 不要忘记添加指向 CaseIterable 实现的原始实现的链接,以便正确归属。
  • @MartinR 我几个月前在 StackOverflow 上发现了它。现在我刚刚从我自己的代码中复制。我真的不记得来源了。但我会尝试
【解决方案2】:

如果您将枚举设为CaseIterable,则可以使用reduce(into:) 构建字典。由于hashValue 现在可以在运行之间更改,我建议使用enumerated() 按顺序对案例进行编号:

enum FruitPriority: String, CaseIterable {
    case PEARS
    case ORANGES
    case APPLES
}

let result = FruitPriority.allCases.enumerated().reduce(into: [:]) { $0[$1.element.rawValue] = $1.offset }

print(result)

// ["ORANGES": 1, "APPLES": 2, "PEARS": 0]

【讨论】:

  • 谢谢你,vacawama,关于reduce into。我正在尝试实现它,因为它看起来简单多了。跨度>
【解决方案3】:

如果您只需要一次调用枚举:

CaseIterable 添加到您的枚举中,然后在枚举中创建函数getDictionary,该函数会返回您的字典(对于每个枚举案例,rawValue 将分配为keyhashValue 作为value

enum FruitPriority: String, CaseIterable {

    case PEARS
    case ORANGES
    case APPLES

    func getDictionary() -> [String: Int] {
        var dictionary = [String: Int]()
        FruitPriority.allCases.forEach {
            dictionary[$0.rawValue] = $0.hashValue
        }
        return dictionary
    }

}

然后你就可以打电话了

var fruitPriorityArray: [String : Int] = FruitPriority.getDictionary()

注意:如果您使用的是早期版本的 Swift,您可以看到 this 来创建 CaseIterable 协议

【讨论】:

  • 谢谢你,罗伯特·德雷斯勒。我会尝试实现你推荐的协议。
猜你喜欢
  • 1970-01-01
  • 2014-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-16
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多