I'm using a swift dictionary of type [UIImage:UIImage], and I'm trying to find a specific key for a given value. In Objective-C I could use allKeysForValue, but there appears to be no such method for a Swift dictionary. What should I be using?
11 Answers
Swift 3: a more performant approach for the special case of bijective dictionaries
If the reverse dictionary lookup use case covers a bijective dictionary with a one to one relationship between keys and values, an alternative approach to the collection-exhaustive filter
operation would be using a quicker short-circuiting approach to find some key, if it exists.
extension Dictionary where Value: Equatable {
func someKey(forValue val: Value) -> Key? {
return first(where: { $1 == val })?.key
}
}
Example usage:
let dict: [Int: String] = [1: "one", 2: "two", 4: "four"]
if let key = dict.someKey(forValue: "two") {
print(key)
} // 2
-
1Awesome. Thank you. – Womble Jun 30 '17 at 04:24
There is, as far as I know, no built-in Swift function to get all dictionary keys for a given value. Here is a possible implementation:
func allKeysForValue<K, V : Equatable>(dict: [K : V], val: V) -> [K] {
return map(filter(dict) { $1 == val }) { $0.0 }
}
The filter
reduces all key-value pairs to those with the given value.
The map
maps the (filtered) key-value pairs to the keys alone.
Example usage:
let dict = ["a" : 1, "b" : 2, "c" : 1, "d" : 2]
let keys = allKeysForValue(dict, 1)
println(keys) // [a, c]
Update for Swift 2: As of Xcode 7 beta 2, this can now be achieved with an extension method for dictionaries of equatable values (thanks to Airspeed Velocity to make me aware of this in a comment):
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]
Update for 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]
-
Is there a way to return the value as a string rather than as an array? In my setup there will always only be a single unique value for every key (it is a japanese to romanji dictionary). – sxflynn Aug 16 '15 at 03:35
-
Just thought I'd mention that I've been using this approach in my project for a while, and noticed today while profiling that it can be *very* slow... looking for an alternative. – jbm Nov 30 '16 at 19:43
-
1@HashemAboonajmi: Thank you for the edit. However, I decided to revert to the previous version because I think that `allKeys(forValue:)` is correct even in Swift 3. Existing methods with similar naming are `index(forKey:)`, `update(value: forKey)`, `value(forKey:)`. – Martin R Apr 27 '17 at 06:42
Understand that most of these answers get the dictionary's entire set of keys before searching through it. This answer uses the first(where:)
method which returns after the key is found.
Swift 5 (inline)
if let key = someDictionary.first(where: { $0.value == someValue })?.key {
// use key
}
Swift 5 (extension)
extension Dictionary where Value: Equatable {
func key(from value: Value) -> Key? {
return self.first(where: { $0.value == value })?.key
}
}
Usage
let key = someDictionary.key(from: someValue)) // optional
if let key = someDictionary.key(from: someValue) {
// non-optional
}

- 11,654
- 3
- 38
- 51
-
6
-
@Adrian note that this answer uses exactly the same approach as the **accepted** answer, which was posted 3 years before this one. This answer fails to mention, however, that one should use this with care, explicitly knowing that it will yield _some_ key, particularly in dictionaries where several keys stores the same value. – dfrib Oct 23 '20 at 21:03
You can use allKeys(for:)
if you cast to NSDictionary
:
let keys = (dict as NSDictionary).allKeys(for: image) as! [UIImage]

- 150,663
- 30
- 266
- 294
-
-
Just a tiny addition, I used this code as a pattern to extract a Int key from a dictionary: `let keys = (ItemDict as NSDictionary).allKeysForObject(orderItems[indexPath.row])` Then you can access like: `let someIntValue = keys[0].integerValue;` Works like a dream, thanks! – c0d3p03t Apr 21 '15 at 21:16
-
Swift 3: `let keys = (dict as NSDictionary).allKeys(for: image) as! [UIImage]` – BitParser Jul 13 '17 at 13:50
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
provides map with searchingValue
which is ["key4":8,"key3":8]
b.keys.first
provides first element of the all filtered keys which is g
a
is the rquired key for value 8

- 621
- 6
- 9
Here's another approach, which I wrote about on my blog. It was tested against 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
}
}
}
It's the most efficient implementation posted to this thread that yields all keys mapped to a specified value, because it uses flatMap
, instead of filter
and then map
. I wrote about flatMap
in my Higher-order functions in Swift article, if you're interested.
Also, because my method is generic (by virtue of being in the Dictionary<Key,Value>
generic class) you don't need to cast its result to the key's type, which is necessary when using allKeysForObject(_:)
from NSDictionary
.

- 884
- 6
- 9
-
Thank you for this, I found it to be a very clean way to accomplish this task. – alexwatever Aug 18 '16 at 14:54
The Swift 2 version:
func allKeysForValue<K, V : Equatable>(dict: [K : V], val: V) -> [K] {
return dict.filter{ $0.1 == val }.map{ $0.0 }
}

- 1,082
- 14
- 24
-
-
Because you are mapping over a dictionary, $0 is a dictionary element. $0.0 is the key and $0.1 is the value. – Teo Sartori Jul 12 '16 at 05:45
-
I'm sorry, I can't get your point. You said *$0 is a dictionary element*, but `key` and `value` are dictionary elements, right? Because `dictionary = [key:valule]`. – JW.ZG Jul 12 '16 at 16:19
-
Do you mean `$0` is the first element in dictionary? Like `[firstKey:firstValue]`? – JW.ZG Jul 12 '16 at 16:20
-
1In Swift Dictionaries are implemented as generic collections. The contents of a collection are accessed by iterating over its elements. In the case of a Dictionary these elements are defined as a tuples of key, value pairs. You can access the individual parts of a tuple using an index, so $0.0 corresponds to the first (a key) and $0.1 to the second (the value related to the key). – Teo Sartori Jul 13 '16 at 06:12
If you need to find some key for a value (i.e. not all of them if there is more than one, but just any arbitrary one):
extension Dictionary where Value: Equatable {
func someKeyFor(value: Value) -> Key? {
guard let index = indexOf({ $0.1 == value }) else {
return nil
}
return self[index].0
}
}
Above returns nil
if there is no such key for a value.

- 9,872
- 5
- 40
- 68
This will work in case you need any key for a specific value. In my case was the easiest approach. Hope that it helps:
Swift 4.1+
extension Dictionary where Key == String, Value: Equatable {
func key(for value: Value) -> Key? {
return compactMap { value == $1 ? $0 : nil }.first
}
}

- 819
- 7
- 4
If you don't know that the values are unique, this is an option:
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: ""),
""
)
You can just filter through the dictionary and find the value that matches the value you're looking for and then get all the keys that are paired with that value in the dictionary.
FYI: someValue
in this answer represents the hypothetical value you're looking for
dictionary.filter{$0.value == someValue}.keys

- 164
- 7