【问题标题】:How do I create dictionary from array of tuples?如何从元组数组创建字典?
【发布时间】:2017-04-28 15:39:27
【问题描述】:

假设我有一组可以识别的对象,我想从中创建字典。我可以像这样轻松地从数组中获取元组:

let tuples = myArray.map { return ($0.id, $0) }

但是我看不到字典的初始化器来获取元组数组。我错过了什么吗?我是否为此功能创建了字典扩展(实际上并不难,但我认为它会默认提供)还是有更简单的方法可以做到这一点?

有扩展代码

extension Dictionary
{
    public init (_ arrayOfTuples : Array<(Key, Value)>)
    {
        self.init(minimumCapacity: arrayOfTuples.count)

        for tuple in arrayOfTuples
        {
            self[tuple.0] = tuple.1
        }
    }
}

【问题讨论】:

  • 为什么要默认?没有将元组数组映射到字典的通用方法。在字典中,每个键都必须是唯一的,在元组数组中,允许任意数量的重复 keys。拿他们怎么办?改写?忽略?
  • 是的,@user28434 是对的。顺便说一句,看看这个stackoverflow.com/a/31447400/4272498
  • 是的,你说得对@user28434,我没想到。
  • 你为什么要创建一个元组数组?您可以直接使用 myArray 中的数据创建字典。

标签: ios swift dictionary tuples


【解决方案1】:

斯威夫特 4

如果你的元组是 (Hashable, String) 你可以使用:

let array = [("key1", "value1"), ("key2", "value2"), ("key3", "value3")]
let dictionary = array.reduce(into: [:]) { $0[$1.0] = $1.1 }
print(dictionary) // ["key1": "value1", "key2": "value2", "key3": "value3"]

【讨论】:

  • 我不知道为什么这被否决了,因为这是解决 OP 提出的问题的最合适的方法。
  • 我❤️这个答案!
【解决方案2】:

斯威夫特 4

为了创建,您可以使用本机 Dictionary 的 init 函数:

Dictionary(uniqueKeysWithValues: [("a", 0), ("b", 1)]) 
// ["b": 1, "a": 0]

Dictionary(uniqueKeysWithValues: [("a", 0), ("b", 1), ("b", 2)])
// Fatal error: Duplicate values for key: 'b'

// takes the first match
Dictionary([("a", 0), ("b", 1), ("a", 2)], uniquingKeysWith: { old, _ in old })
// ["b": 1, "a": 0]

// takes the latest match
Dictionary([("a", 0), ("b", 1), ("a", 2)], uniquingKeysWith: { $1 }) 
// ["b": 1, "a": 2]

如果你想拥有快捷方式:

Dictionary([("a", 0), ("b", 1), ("a", 2)]) { $1 } 
// ["b": 1, "a": 2]

【讨论】:

    【解决方案3】:

    根据你想做什么,你可以:

    let tuples = [(0, "0"), (1, "1"), (1, "2")]
    var dictionary = [Int: String]()
    

    选项 1:替换现有密钥

    tuples.forEach {
        dictionary[$0.0] = $0.1
    }    
    print(dictionary) //prints [0: "0", 1: "2"]
    

    选项 2:不允许重复键

    enum Errors: Error {
        case DuplicatedKeyError
    }
    
    do {
        try tuples.forEach {
            guard dictionary.updateValue($0.1, forKey:$0.0) == nil else { throw Errors.DuplicatedKeyError }
        }
        print(dictionary)
    } catch {
        print("Error") // prints Error
    }
    

    【讨论】:

      【解决方案4】:

      通用方法:

      /**
       * Converts tuples to dict
       */
      func dict<K,V>(_ tuples:[(K,V)])->[K:V]{
          var dict:[K:V] = [K:V]()
          tuples.forEach {dict[$0.0] = $0.1}
          return dict
      }
      

      函数式编程更新:

      func dict<K,V>(tuples:[(K,V)])->[K:V]{
          return tuples.reduce([:]) {
             var dict:[K:V] = $0
             dict[$1.0] = $1.1   
             return dict
          }
      }
      

      【讨论】:

      • @hasen 这值得商榷。由于您将元组作为参数传递,因此绝对不应该只是 func。将其设为静态明确表示它无法更改其所在类的状态
      • 它不需要驻留在类中。这只是一个功能。 Swift 不是 Java。
      • @hasen 我想这是自以为是的 ? 为了简洁起见,我将其更改为 func。感谢您的意见。
      • 我把这个函数作为字典扩展初始化。
      • @DanielT。已经有一个原生的了:init(uniqueKeysWithValues:) ? (swift 4)
      【解决方案5】:

      使用扩展改进了@GitSync 答案。

      extension Array {
          func toDictionary<K,V>() -> [K:V] where Iterator.Element == (K,V) {
              return self.reduce([:]) {
                  var dict:[K:V] = $0
                  dict[$1.0] = $1.1
                  return dict
              }
          }
      }
      

      【讨论】:

        【解决方案6】:

        更新到@Stefan 的回答。

        extension Array {
        
            func toDictionary<K, V>() -> [K: V] where Iterator.Element == (K, V) {
                return Dictionary(uniqueKeysWithValues: self)
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-05-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-03-21
          相关资源
          最近更新 更多