2016-02-24 27 views
10

In Swift, sto cercando di appiattire una serie di dizionari in un unico dizionario cioèSwift: Appiattire una serie di dizionari di un dizionario

let arrayOfDictionaries = [["key1": "value1"], ["key2": "value2"], ["key3": "value3", "key4": "value4"]] 


//the end result will be: 
flattenedArray = ["key1": "value1", "key2": "value2", "key3": "value3", "key4": "value4"] 

Ho provato con flatmap, ma il tipo del risultato restituito è [(String, AnyObject)] e non [String, Object] cioè

let flattenedArray = arrayOfDictionaries.flatMap { $0 } 
// type is [(String, AnyObject)] 

Così ho 2 domande:

  • Perché viene restituito il tipo [(String, AnyObject)]? E cosa significano le parentesi?

  • Come ottenere il risultato desiderato?

Edit: io preferirei usare un approccio funzionale con la mappa di Swift/flatmap/ridurre ecc invece di un ciclo for

risposta

10

cosa significano le parentesi?

Questo, insieme con una virgola al posto di due punti, dovrebbe fornire il primo indizio: parentesi significa che si ottiene una serie di tuple. Dato che stai cercando un dizionario, non un array, questo ti dice che devi convertire la sequenza di tuple (coppie chiave-valore) in un singolo dizionario.

Come ottenere il risultato desiderato?

Un modo per farlo sarebbe utilizzando reduce, in questo modo: risposta

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

Signore, hai fatto un piccolo errore l'ho risolto :) Controlla il Modifica –

+0

Qui c'era un problema "dict.updateValue (tupla .0, forKey: tuple.1) "Ho cambiato in dict.updateValue (tuple.1, forKey: tuple.0) –

+0

@ O-mkar Ah, lo vedo, grazie! – dasblinkenlight

1

Ecco il modo per farlo

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"]!) 

USCITA

OUTPUT

+0

Grazie per questo. Anche se questo approccio è corretto, preferirei usare un approccio funzionale con la mappa/ridimensionamento/ridimensionamento di Swift. – Lneuner

3

Aggiornamento @ di dasblinkenlight per Swift 3.

"var" nei parametri è stato deprecato, ma questo l'approccio ha funzionato bene per me.

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

il nextDict dovrebbe essere un 'var' not' let' – Wismin

4

Con Swift 4, Dictionay ha un inizializzatore init(_:uniquingKeysWith:). init(_:uniquingKeysWith:) ha la seguente dichiarazione:

init<S>(_ keysAndValues: S, uniquingKeysWith combine: (Value, Value) throws -> Value) rethrows where S : Sequence, S.Element == (Key, Value) 

creare un nuovo dizionario dalle coppie di valori-chiave nella sequenza proposta, utilizzando una chiusura combinano per determinare il valore di duplicati delle chiavi.


I seguenti frammenti di codice mostrano come parco giochi per appiattire una serie di dizionari in un nuovo dizionario.

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] 
+0

Perché queste caratteristiche di Swift 4 sono state create per "inizializzare da una sequenza di' (Chiave, Valore) 'tuple 'piuttosto (o anche) di" una sequenza di dizionari "? Ciò impone l'inclusione del passo 'tupleArray' nel codice, che è piuttosto fastidioso. – pkamb