web-dev-qa-db-ja.com

Swift:辞書の配列を1つの辞書にフラット化します

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などで機能的なアプローチを使用したいと思います

13
Lneuner

角かっこはどういう意味ですか?

これは、コロンの代わりにコンマとともに、最初の手がかりを提供する必要があります。角かっこは、タプルの配列を取得することを意味します。配列ではなく辞書を探しているので、これは、タプルのシーケンス(キーと値のペア)を単一の辞書に変換する必要があることを示しています。

どうすれば望ましい結果を得ることができますか?

これを行う1つの方法は、次のようにreduceを使用することです。

let flattenedDictionary = arrayOfDictionaries
    .flatMap { $0 }
    .reduce([String:String]()) { (var dict, Tuple) in
        dict.updateValue(Tuple.1, forKey: Tuple.0)
        return dict
    }
13
dasblinkenlight

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
    }
6
Mars

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]
6
Imanou Petit

これがその方法です

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

1
O-mkar