Swiftでは、辞書の配列を1つの辞書にフラット化しようとしています。
_let arrayOfDictionaries = [["key1": "value1"], ["key2": "value2"], ["key3": "value3", "key4": "value4"]]
//the end result will be:
flattenedArray = ["key1": "value1", "key2": "value2", "key3": "value3", "key4": "value4"]
_
フラットマップを使用してみましたが、返される結果のタイプは[(String, AnyObject)]
であり、_[String, Object]
_ではありません。
_let flattenedArray = arrayOfDictionaries.flatMap { $0 }
// type is [(String, AnyObject)]
_
だから私は2つの質問があります:
タイプ[(String、AnyObject)]が返されるのはなぜですか?そして、括弧はどういう意味ですか?
どうすれば望ましい結果を得ることができますか?
編集:forループの代わりにSwiftのmap/flatmap/reduceなどで機能的なアプローチを使用したいと思います
角かっこはどういう意味ですか?
これは、コロンの代わりにコンマとともに、最初の手がかりを提供する必要があります。角かっこは、タプルの配列を取得することを意味します。配列ではなく辞書を探しているので、これは、タプルのシーケンス(キーと値のペア)を単一の辞書に変換する必要があることを示しています。
どうすれば望ましい結果を得ることができますか?
これを行う1つの方法は、次のようにreduce
を使用することです。
let flattenedDictionary = arrayOfDictionaries
.flatMap { $0 }
.reduce([String:String]()) { (var dict, Tuple) in
dict.updateValue(Tuple.1, forKey: Tuple.0)
return dict
}
Swift 3の@dasblinkenlightの回答を更新します。
パラメータの「var」は非推奨になりましたが、このアプローチは私にとっては問題なく機能しました。
let flattenedDictionary = arrayOfDictionaries
.flatMap { $0 }
.reduce([String:String]()) { (dict, Tuple) in
var nextDict = dict
nextDict.updateValue(Tuple.1, forKey: Tuple.0)
return nextDict
}
Swift 5、Dictionay
には init(_:uniquingKeysWith:)
初期化子があります。init(_:uniquingKeysWith:)
には次の宣言があります:
init<S>(_ keysAndValues: S, uniquingKeysWith combine: (Value, Value) throws -> Value) rethrows where S : Sequence, S.Element == (Key, Value)
結合クロージャを使用して重複キーの値を決定し、指定されたシーケンスのキーと値のペアから新しいディクショナリを作成します。
次の2つのPlaygroundサンプルコードは、辞書の配列を新しい辞書にフラット化する方法を示しています。
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]