Подтвердить что ты не робот

Словарь Swift: фильтр

я пытаюсь отфильтровать словарь в swift:

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

приведенный выше код фильтра компилируется в swift 2, но выдает следующую ошибку:

Невозможно присвоить значение типа '[(String, String)]' значению типа '[String: String]'

это ошибка в компиляторе swift или это не правильный способ фильтровать словари в swift?

Заранее большое спасибо!

4b9b3361

Ответ 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/...