2015-09-16 50 views
36

sto provando a filtrare un dizionario in rapida:Swift: Filtro dizionario

var data: [String: String] = [:] 
data = data.filter { $0.1 == "Test" } 

il codice del filtro compila sopra in rapida 2, ma si ottiene il seguente errore:

Cannot assign a value of type '[(String, String)]' to a value of type '[String : String]' 

è presente un bug in il compilatore veloce o non è questo il modo giusto per filtrare i dizionari in modo rapido?

Grazie mille in anticipo!

risposta

57

Questo è stato risolto in Swift 4

let data = ["a": 0, "b": 42] 
let filtered = data.filter { $0.value > 10 } 
print(filtered) // ["b": 42] 

a Swift 4, un dizionario filtrato restituisce un dizionario.


risposta originale per Swift 2 e 3

Il problema è che data è un dizionario, ma il risultato di filter è un array, in modo che il messaggio di errore dice che non è possibile assegnare il risultato di quest'ultimo al primo.

Si potrebbe semplicemente creare una nuova variabile/costante per l'array risultante:

let data: [String: String] = [:] 
let filtered = data.filter { $0.1 == "Test" } 

Qui filtered è un array di tuple: [(String, String)].

Una volta filtrato, è possibile ricreare un nuovo dizionario, se questo è quello che vi serve:

var newData = [String:String]() 
for result in filtered { 
    newData[result.0] = result.1 
} 

Se si decide di non utilizzare filter si potrebbe mutare il dizionario originale o una copia di esso:

var data = ["a":"Test", "b":"nope"] 
for (key, value) in data { 
    if value != "Test" { 
     data.removeValueForKey(key) 
    } 
} 
print(data) // ["a": "Test"] 

Nota: in Swift 3, removeValueForKey è stato rinominato removeValue(forKey:), quindi in questo esempio diventa data.removeValue(forKey: key).

+19

okay grazie :) questo è semplicemente stupido da apple secondo me. Quando filtro un dizionario mi aspetto un dizionario in cambio ... Ho cambiato il mio codice per essere un array e utilizzare una struttura combinata per includere sia la chiave che il valore (in modo che non sono obbligato a usare le chiavi stringa) e Io uso di nuovo la funzione filtro, poiché questo è l'approccio più conciso. – warly

+4

Qualcuno sa perché Dictionary.filter non restituisce un dizionario? Sono curioso. – Tylerc230

+0

@warly vedi la risposta di Eendje sotto. È una risposta diversa – Honey

13
data.forEach { if $1 != "Test" { data[$0] = nil } } 

Solo un altro approccio (un po 'semplificata) per filtrare gli oggetti nel vostro dizionario.

7

Per documenti di Apple, il filtro:

Returns an array containing, in order, the elements of the sequence that satisfy the given predicate.

https://developer.apple.com/reference/swift/sequence/1641239-filter

ho trovato me stesso bisogno di fare quello che il PO è stato chiesto circa e ha finito per scrivere le seguenti estensioni (Swift 3):

extension Dictionary 
{ 
    func filteredDictionary(_ isIncluded: (Key, Value) -> Bool) -> Dictionary<Key, Value> 
    { 
    return self.filter(isIncluded).toDictionary(byTransforming: { $0 }) 
    } 
} 

extension Array 
{ 
    func toDictionary<H:Hashable, T>(byTransforming transformer: (Element) -> (H, T)) -> Dictionary<H, T> 
    { 
    var result = Dictionary<H,T>() 
    self.forEach({ element in 
     let (key,value) = transformer(element) 
     result[key] = value 
    }) 
    return result 
    } 
} 

Utilizzo:

let data = ["a":"yes", "b":"nope", "c":"oui", "d":"nyet"] 
let filtered = data.filteredDictionary({ $0.1 >= "o" }) 

// filtered will be a dictionary containing ["a": "yes", "c": "oui"] 
0

ho trovato questo metodo per essere utile dopo il filtraggio o applicare qualche altra trasformazione che si traduce in un array di elementi del dizionario:

extension Array { 
    func dictionary<K: Hashable, V>() -> [K: V] where Element == Dictionary<K, V>.Element { 
     var dictionary = [K: V]() 
     for element in self { 
      dictionary[element.key] = element.value 
     } 
     return dictionary 
    } 
} 

Per usarlo, basta dire qualcosa come:

dictionary = dictionary.filter{ $0.key == "test" }.dictionary() 

Il vantaggio di questo metodo è che nessun argomento di alcun tipo deve essere passato al metodo dictionary(). Gli argomenti di tipo generico dicono al compilatore tutto ciò che deve sapere.

+0

Non riesco a compilare con questo show questo errore: 'Mostra tutti i numeri /Users/XXXX/Desktop/Work4/BitBucketRepo/XXXX-XXX/XXXXX/XXXXX/Sources/Utils/Extensions/NSArray+Utils.swift:12 : 63: Lo stesso tipo richiede il parametro generico 'Elemento' non generico' '/ Users/XXXX/Desktop/Work4/BitBucketRepo/XXX-XXX-XXX/XXXXX/XXXXX/Sources/Utils/Estensioni/NSArray + Utils .swift: 15: 24: il valore del tipo 'Elemento' non ha 'chiave' membro ' –

+0

@ReinierMelian: Non so quale problema stai avendo. Incolla il contenuto di [questo codice] (https://pastebin.com/FA9vvv15) in un Xcode Playground e vedrai che funziona perfettamente. Assicurati di utilizzare l'ultima versione di Swift. –

Problemi correlati