Swift dictionary get key for value

我使用了一个类型为[ UIImage: UIImage ]的快速字典,并试图为给定的值找到一个特定的键。在 Objective-C 中,我可以使用 allKeysForValue,但似乎没有这样的方法用于 Swift 字典。我该用什么?

83004 次浏览

据我所知,没有内置的 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]

如果你转换到 NSDictionary,你可以使用 allKeys(for:):

let keys = (dict as NSDictionary).allKeys(for: image) as! [UIImage]

Swift 2版本:

func allKeysForValue<K, V : Equatable>(dict: [K : V], val: V) -> [K] {
return dict.filter{ $0.1 == val }.map{ $0.0 }
}

如果您需要为一个值找到 一些键(即,如果有多个值,则不是 所有键,而是任意一个值) :

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

这是我写的另一个关于 在我的博客上的方法,它是针对 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。如果你感兴趣的话,我在我的 Swift 中的高阶函数文章中写了关于 flatMap的内容。

另外,由于我的方法是泛型的(因为属于 Dictionary<Key,Value>泛型类) ,所以不需要将其结果强制转换为键的类型,这在使用 NSDictionary中的 allKeysForObject(_:)时是必需的。

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
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 提供了所有过滤键的第一个元素,即 < em > g

a 是 value < em > 8所需的键

如果您需要特定值的任何键,这将起作用。对我来说,这是最简单的方法。希望对你有所帮助:

Swift 4.1 +

extension Dictionary where Key == String, Value: Equatable {
func key(for value: Value) -> Key? {
return compactMap { value == $1 ? $0 : nil }.first
}
}

要知道,这些答案中的大多数在查找之前都会得到字典中的整套键。这个答案使用 first(where:)方法,该方法在找到密钥后返回。

Swift 5(内联)

if let key = someDictionary.first(where: { $0.value == someValue })?.key {
// use key
}

Swift 5(扩展)

extension Dictionary where Value: Equatable {
func key(from value: Value) -> Key? {
return self.first(where: { $0.value == value })?.key
}
}

用法

let key = someDictionary.key(from: someValue)) // optional


if let key = someDictionary.key(from: someValue) {
// non-optional
}

如果你不知道这些值是唯一的,这是一个选项:

public extension Dictionary where Value: Equatable {
/// The only key that maps to `value`.
/// - Throws: `OnlyMatchError`
func onlyKey(for value: Value) throws -> Key {
try onlyMatch { $0.value == value } .key
}
}
public extension Sequence {
/// The only match for a predicate.
/// - Throws: `OnlyMatchError`
func onlyMatch(for getIsMatch: (Element) throws -> Bool) throws -> Element {
guard let onlyMatch: Element = (
try reduce(into: nil) { onlyMatch, element in
switch ( onlyMatch, try getIsMatch(element) ) {
case (_, false):
break
case (nil, true):
onlyMatch = element
case (.some, true):
throw onlyMatchError.moreThanOneMatch
}
}
) else { throw onlyMatchError.noMatches }


return onlyMatch
}
}


/// An error thrown from a call to `onlyMatch`.
public enum OnlyMatchError: Error {
case noMatches
case moreThanOneMatch
}
XCTAssertEqual(
try ["skunky": "monkey", "🦨": "🐒"].onlyKey(for: "🐒"),
"🦨"
)

你可以通过字典过滤,找到与你要找的值相匹配的值,然后在字典中找到所有与这个值相匹配的键。

供参考: 这个答案中的 someValue表示您所寻找的假设值

dictionary.filter{$0.value == someValue}.keys