Я использую быстрый словарь типа [UIImage: UIImage], и я пытаюсь найти конкретный ключ для данного значения. В Objective-C я мог бы использовать allKeysForValue, но, похоже, такого метода для словаря Swift не существует. Что я должен использовать?
Словарь Swift - ключ к значению
Ответ 1
Вы можете использовать allKeys(for:)
, если вы добавили к NSDictionary
:
let keys = (dict as NSDictionary).allKeys(for: image) as! [UIImage]
Ответ 2
Есть, насколько я знаю, нет встроенной функции Swift для получения всех ключей словаря для данного значения. Вот возможная реализация:
func allKeysForValue<K, V : Equatable>(dict: [K : V], val: V) -> [K] {
return map(filter(dict) { $1 == val }) { $0.0 }
}
filter
сводит все пары ключ-значение к значениям с заданным значением.
map
отображает (отфильтрованные) пары ключ-значение только на ключи.
Пример использования:
let dict = ["a" : 1, "b" : 2, "c" : 1, "d" : 2]
let keys = allKeysForValue(dict, 1)
println(keys) // [a, c]
Обновление для Swift 2: Как и в случае с Xcode 7 beta 2, теперь это можно сделать с методом расширения для словарей равных значений (спасибо Скорость воздушной скорости, чтобы сообщить об этом в комментарий):
extension Dictionary where Value : Equatable {
func allKeysForValue(val : Value) -> [Key] {
return self.filter { $1 == val }.map { $0.0 }
}
}
let dict = ["a" : 1, "b" : 2, "c" : 1, "d" : 2]
let keys = dict.allKeysForValue(1)
print(keys) // [a, c]
Обновление для Swift 3:
extension Dictionary where Value: Equatable {
func allKeys(forValue val: Value) -> [Key] {
return self.filter { $1 == val }.map { $0.0 }
}
}
let dict = ["a" : 1, "b" : 2, "c" : 1, "d" : 2]
let keys = dict.allKeys(forValue: 1)
print(keys) // [a, c]
Ответ 3
Swift 3: более эффективный подход для специального случая биективных словарей
Если использование обратного словаря для поиска в словарях обратного словаря содержит биективный словарь с индивидуальной зависимостью между ключами и значениями, альтернативный подход к операции исчерпывающей коллекции filter
будет использовать более быстрый подход короткого замыкания для поиска некоторого ключа, если он существует.
extension Dictionary where Value: Equatable {
func someKey(forValue val: Value) -> Key? {
return first(where: { $1 == val })?.key
}
}
Пример использования:
let dict: [Int: String] = [1: "one", 2: "two", 4: "four"]
if let key = dict.someKey(forValue: "two") {
print(key)
} // 2
Ответ 4
Вот еще один подход, о котором я писал в в своем блоге. Он был протестирован против Swift 2.2.
extension Dictionary where Value: Equatable {
/// Returns all keys mapped to the specified value.
/// ```
/// let dict = ["A": 1, "B": 2, "C": 3]
/// let keys = dict.keysForValue(2)
/// assert(keys == ["B"])
/// assert(dict["B"] == 2)
/// ```
func keysForValue(value: Value) -> [Key] {
return flatMap { (key: Key, val: Value) -> Key? in
value == val ? key : nil
}
}
}
Это самая эффективная реализация, отправленная в этот поток, который дает все ключи, сопоставленные указанному значению, потому что он использует flatMap
вместо filter
, а затем map
. Я писал о flatMap
в моей функции более высокого порядка в Swift, если вам интересно.
Кроме того, поскольку мой метод является общим (благодаря наличию в классе Dictionary<Key,Value>
generic), вам не нужно указывать его результат на тип ключа, который необходим при использовании allKeysForObject(_:)
из NSDictionary
.
Ответ 5
Версия Swift 2:
func allKeysForValue<K, V : Equatable>(dict: [K : V], val: V) -> [K] {
return dict.filter{ $0.1 == val }.map{ $0.0 }
}
Ответ 6
Если вам нужно найти какой-либо ключ для значения (т.е. не все из них, если их больше одного, но только любое произвольное):
extension Dictionary where Value: Equatable {
func someKeyFor(value: Value) -> Key? {
guard let index = indexOf({ $0.1 == value }) else {
return nil
}
return self[index].0
}
}
Выше возвращается nil
, если такой ключ для значения отсутствует.
Ответ 7
let dict = ["key1":2,"key2":6,"key3":8,"key4":8]
let searchingValue = 8
let b = dict.filter {$0.value == searchingValue}
let a = b.keys.first
b
предоставляет карту с searchingValue
которая ["key4":8,"key3":8]
b.keys.first
обеспечивает первый элемент из всех отфильтрованных ключей, который g
a
- требуемый ключ для значения 8
Ответ 8
Это будет работать, если вам нужен какой-либо ключ для определенного значения. В моем случае был самый простой подход. Надеюсь, что это поможет:
Свифт 4. 1+
extension Dictionary where Key == String, Value: Equatable {
func key(for value: Value) -> Key? {
return compactMap { value == $1 ? $0 : nil }.first
}
}
Ответ 9
Swift 5 без удлинителя
По какой-то причине подобные вопросы всегда вызывают ответы, которые используют extension
. Если вам нужен ключ для определенного значения из единственного словаря или только одного раза и вы не хотите (и не должны) расширять весь объект Foundation для одноразового случая, сделайте это вручную:
var imageDictionary = [UIImage: UIImage]()
func getKey(for value: UIImage) {
if let entry = imageDictionary.first(where: { (_, v) -> Bool in
return v == value
}) {
print(entry.key)
}
}