Swift: Flatten an array of dictionaries to one dictionary
what do the brackets mean?
This, along with a comma instead of a colon, should provide the first clue: brackets mean that you get an array of tuples. Since you are looking for a dictionary, not an array, this tells you that you need to convert the sequence of tuples (key-value pairs) to a single dictionary.
How do I achieve the desired result?
One way to do it would be using reduce
, like this:
let flattenedDictionary = arrayOfDictionaries
.flatMap { $0 }
.reduce([String:String]()) { (var dict, tuple) in
dict.updateValue(tuple.1, forKey: tuple.0)
return dict
}
Updating @dasblinkenlight's answer for Swift 3.
"var" in the parameters has been deprecated, but this approach worked fine for me.
let flattenedDictionary = arrayOfDictionaries
.flatMap { $0 }
.reduce([String:String]()) { (dict, tuple) in
var nextDict = dict
nextDict.updateValue(tuple.1, forKey: tuple.0)
return nextDict
}
With Swift 5, Dictionay
has a init(_:uniquingKeysWith:)
initializer. init(_:uniquingKeysWith:)
has the following declaration:
init<S>(_ 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.
The two following Playground sample codes show how to flatten an array of dictionaries into a new dictionary.
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"]
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]