Swift: filtro de diccionario

Estoy tratando de filtrar un diccionario rápidamente:

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

el código de filtro anterior comstack bajo swift 2 pero produce el siguiente error:

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

¿Es esto un error en el comstackdor veloz o esta no es la forma correcta de filtrar los diccionarios de forma rápida?

¡Muchas gracias por adelantado!

Esto ha sido arreglado en Swift 4

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

En Swift 4, un diccionario filtrado devuelve un diccionario.


Respuesta original para Swift 2 y 3

El problema es que los data son un diccionario, pero el resultado del filter es una matriz, por lo que el mensaje de error dice que no se puede asignar el resultado de la última al primero.

Podrías simplemente crear una nueva variable / constante para tu matriz resultante:

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

Aquí se filtered una matriz de tuplas: [(String, String)] .

Una vez filtrado, puede recrear un nuevo diccionario si esto es lo que necesita:

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

Si decide no usar el filter , puede mutar el diccionario original o una copia del mismo:

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

Nota: en Swift 3, removeValueForKey ha cambiado de nombre removeValue(forKey:) , por lo que en este ejemplo se convierte en data.removeValue(forKey: key) .

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

Solo otro enfoque (un poco simplificado) para filtrar objetos en su diccionario.

Según los documentos de Apple, filtra:

Devuelve una matriz que contiene, en orden, los elementos de la secuencia que satisfacen el predicado dado.

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

Me di cuenta de que necesitaba hacer lo que el OP estaba preguntando y terminé escribiendo las siguientes extensiones (Swift 3):

 extension Dictionary { func filteredDictionary(_ isIncluded: (Key, Value) -> Bool) -> Dictionary { return self.filter(isIncluded).toDictionary(byTransforming: { $0 }) } } extension Array { func toDictionary(byTransforming transformer: (Element) -> (H, T)) -> Dictionary { var result = Dictionary() self.forEach({ element in let (key,value) = transformer(element) result[key] = value }) return result } } 

Uso:

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

He encontrado que este método es útil después de filtrar o aplicar alguna otra transformación que da como resultado una matriz de elementos del diccionario:

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

Para usarlo, solo di algo como:

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

La ventaja de este método es que no se debe pasar ningún argumento de ningún tipo al método dictionary() . Los argumentos de tipo genérico le dicen al comstackdor todo lo que necesita saber.