Il dizionario di Swift trova la chiave per il valore

Sto usando un dizionario veloce di tipo [UIImage: UIImage], e sto cercando di trovare una chiave specifica per un determinato valore. In Objective-C potrei usare allKeysForValue, ma sembra che non ci sia un tale metodo per un dizionario Swift. Cosa dovrei usare?

Puoi usare allKeys(for:) se lanci su NSDictionary :

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

Non c’è, per quanto ne so, nessuna funzione Swift incorporata per ottenere tutte le chiavi del dizionario per un determinato valore. Ecco una ansible implementazione:

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

Il filter riduce tutte le coppie chiave-valore a quelle con il valore dato. La map mappa le coppie di valori-chiave (filtrate) solo con le chiavi.

Esempio di utilizzo:

 let dict = ["a" : 1, "b" : 2, "c" : 1, "d" : 2] let keys = allKeysForValue(dict, 1) println(keys) // [a, c] 

Aggiornamento per Swift 2: A partire da Xcode 7 beta 2, questo può ora essere ottenuto con un metodo di estensione per dizionari di valori equi (grazie ad Airspeed Velocity per rendermene conto in un commento ):

 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] 

Aggiornamento per 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] 

Swift 3: un approccio più performante per il caso speciale dei dizionari biettivi

Se il caso d’uso di ricerca del dizionario inverso copre un dizionario biettivo con una relazione uno a uno tra chiavi e valori, un approccio alternativo all’operazione di filter esauriente di raccolta utilizzerebbe un approccio di cortocircuito più rapido per trovare qualche chiave, se esiste.

 extension Dictionary where Value: Equatable { func someKey(forValue val: Value) -> Key? { return first(where: { $1 == val })?.key } } 

Esempio di utilizzo:

 let dict: [Int: String] = [1: "one", 2: "two", 4: "four"] if let key = dict.someKey(forValue: "two") { print(key) } // 2 

Ecco un altro approccio, di cui ho scritto sul mio blog . È stato testato contro 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 } } } 

È l’implementazione più efficiente pubblicata su questo thread che restituisce tutte le chiavi mappate su un valore specificato, poiché utilizza flatMap , anziché il filter e quindi la map . Ho scritto su flatMap nelle mie funzioni di ordine superiore nell’articolo Swift , se sei interessato.

Inoltre, poiché il mio metodo è generico (in virtù dell’essere nella class Dictionary generic) non è necessario allKeysForObject(_:) suo risultato al tipo di chiave, che è necessario quando si utilizza allKeysForObject(_:) da NSDictionary .

La versione Swift 2:

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

Se hai bisogno di trovare qualche chiave per un valore (cioè non tutti se ce ne sono più di uno, ma solo uno qualsiasi):

 extension Dictionary where Value: Equatable { func someKeyFor(value: Value) -> Key? { guard let index = indexOf({ $0.1 == value }) else { return nil } return self[index].0 } } 

Sopra ritorna nil se non esiste una chiave di questo tipo per un valore.

 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 fornisce una mappa con ["key4":8,"key3":8] che è ["key4":8,"key3":8]

b.keys.first fornisce il primo elemento di tutte le chiavi filtrate che è g

a è la chiave richiesta per il valore 8