Swift: Flatten an array of dictionaries to one dictionary
在 Swift 中,我正在尝试将一组字典扁平化为一个字典
即
1 2 3 4 5 | let arrayOfDictionaries = [["key1":"value1"], ["key2":"value2"], ["key3":"value3","key4":"value4"]] //the end result will be: flattenedArray = ["key1":"value1","key2":"value2","key3":"value3","key4":"value4"] |
我尝试过使用flatmap,但是返回结果的类型是
1 2 | let flattenedArray = arrayOfDictionaries.flatMap { $0 } // type is [(String, AnyObject)] |
所以我有两个问题:
-
为什么返回类型[(String, AnyObject)]?括号是什么意思?
-
我怎样才能达到预期的效果?
编辑:我更喜欢使用 Swift 的 map/flatmap/reduce 等功能方法,而不是 for-loop
what do the brackets mean?
这与逗号而不是冒号一起应该提供第一个线索:括号意味着你得到一个元组数组。由于您要查找的是字典,而不是数组,这告诉您需要将元组序列(键值对)转换为单个字典。
How do I achieve the desired result?
一种方法是使用
1 2 3 4 5 6 | let flattenedDictionary = arrayOfDictionaries .flatMap { $0 } .reduce([String:String]()) { (var dict, tuple) in dict.updateValue(tuple.1, forKey: tuple.0) return dict } |
在 Swift 5 中,
1 | init(_ keysAndValues: S, uniquingKeysWith combine: (Value, Value) throws -> Value) rethrows where S : Sequence, S.Element == (Key, Value) |
Creates a new dictionary from the key-value pairs in the given sequence, using a combining closure to determine the value for any duplicate keys.
以下两个 Playground 示例代码展示了如何将字典数组展平为新字典。
1 2 3 4 5 6 | let dictionaryArray = [["key1":"value1"], ["key1":"value5","key2":"value2"], ["key3":"value3"]] let tupleArray: [(String, String)] = dictionaryArray.flatMap { $0 } let dictonary = Dictionary(tupleArray, uniquingKeysWith: { (first, last) in last }) print(dictonary) // prints ["key2":"value2","key3":"value3","key1":"value5"] |
1 2 3 4 5 6 7 | let dictionaryArray = [["key1": 10], ["key1": 10,"key2": 2], ["key3": 3]] let tupleArray: [(String, Int)] = dictionaryArray.flatMap { $0 } let dictonary = Dictionary(tupleArray, uniquingKeysWith: { (first, last) in first + last }) //let dictonary = Dictionary(tupleArray, uniquingKeysWith: +) // also works print(dictonary) // ["key2": 2,"key3": 3,"key1": 20] |
更新@dasblinkenlight 对 Swift 3 的回答。
参数中的"var"已被弃用,但这种方法对我来说效果很好。
1 2 3 4 5 6 7 | let flattenedDictionary = arrayOfDictionaries .flatMap { $0 } .reduce([String:String]()) { (dict, tuple) in var nextDict = dict nextDict.updateValue(tuple.1, forKey: tuple.0) return nextDict } |
这里是做
的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 | let arrayOfDictionaries = [["key1":"value1"], ["key2":"value2"], ["key3":"value3","key4":"value4"]] var dic = [String: String]() for item in arrayOfDictionaries { for (kind, value) in item { print(kind) dic.updateValue(value, forKey: kind) } } print(dic) print(dic["key1"]!) |
OUTPUT