Словарь Swift: фильтр
я пытаюсь отфильтровать словарь в swift:
var data: [String: String] = [:]
data = data.filter { $0.1 == "Test" }
приведенный выше код фильтра компилируется в swift 2, но выдает следующую ошибку:
Невозможно присвоить значение типа '[(String, String)]' значению типа '[String: String]'
это ошибка в компиляторе swift или это не правильный способ фильтровать словари в swift?
Заранее большое спасибо!
Ответы
Ответ 1
Это было исправлено в Swift 4
let data = ["a": 0, "b": 42]
let filtered = data.filter { $0.value > 10 }
print(filtered) // ["b": 42]
В Swift 4 отфильтрованный словарь возвращает словарь.
Оригинальный ответ для Swift 2 и 3
Проблема заключается в том, что data
является словарем, но результатом filter
является массив, поэтому в сообщении об ошибке говорится, что вы не можете назначить результат последнего первому.
Вы можете просто создать новую переменную/константу для вашего результирующего массива:
let data: [String: String] = [:]
let filtered = data.filter { $0.1 == "Test" }
Здесь filtered
- массив кортежей: [(String, String)]
.
После фильтрации вы можете воссоздать новый словарь, если это вам нужно:
var newData = [String:String]()
for result in filtered {
newData[result.0] = result.1
}
Если вы решите не использовать filter
, вы можете изменить исходный словарь или его копию:
var data = ["a":"Test", "b":"nope"]
for (key, value) in data {
if value != "Test" {
data.removeValueForKey(key)
}
}
print(data) // ["a": "Test"]
Примечание: в Swift 3, removeValueForKey
был переименован removeValue(forKey:)
, поэтому в этом примере он становится data.removeValue(forKey: key)
.
Ответ 2
data.forEach { if $1 != "Test" { data[$0] = nil } }
Еще один подход (немного упрощенный) для фильтрации объектов в вашем словаре.
Ответ 3
В Apple документы, фильтр:
Возвращает массив, содержащий, по порядку, элементы последовательности, которые удовлетворяют данному предикату.
https://developer.apple.com/reference/swift/sequence/1641239-filter
Мне было нужно делать то, о чем спрашивал OP, и в итоге написала следующие расширения (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
}
}
Использование:
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"]
Ответ 4
Я нашел, что этот метод полезен после фильтрации или применения какого-либо другого преобразования, которое приводит к массиву элементов словаря:
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
}
}
Чтобы использовать его, просто скажите что-то вроде:
dictionary = dictionary.filter{ $0.key == "test" }.dictionary()
Преимущество этого метода заключается в том, что никакие аргументы какого-либо типа не должны передаваться методу dictionary()
. Общие аргументы типа сообщают компилятору все, что ему нужно знать.
Ответ 5
Пожалуйста, проверьте сложный словарь, как массив словаря, я надеюсь, это поможет вам! Благодарю вас
fooobar.com/info/1259659/...