Swiftタイプ[UIImage:UIImage]の辞書を使用しています。特定の値の特定のキーを見つけようとしています。Objective-CではallKeysForValueを使用できますが、 Swift辞書のためのそのようなメソッドではないようです。私は何を使うべきですか?
NSDictionary
にキャストする場合は、allKeys(for:)
を使用できます。
let keys = (dict as NSDictionary).allKeys(for: image) as! [UIImage]
私の知る限り、特定の値のすべての辞書キーを取得する組み込みの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:のアップデート。Xcode7ベータ2の時点で、これは等値の辞書の拡張メソッドで実現できます( Airspeed Velocitya 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]
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]
逆辞書検索のユースケースが、キーと値の間の1対1の関係を持つ全単射辞書を対象とする場合、コレクションを網羅するfilter
操作の代替アプローチは、より高速な短絡アプローチを使用して見つけることです- someキー(存在する場合)。
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
私のブログで について書いた別のアプローチがあります。 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(_:)
を使用する場合に必要です。
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
値のsomeキーを見つける必要がある場合(つまり、複数ある場合はallではなく、任意の1つだけ):
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バージョン:
func allKeysForValue<K, V : Equatable>(dict: [K : V], val: V) -> [K] {
return dict.filter{ $0.1 == val }.map{ $0.0 }
}
Swift 5拡張子なし
何らかの理由で、これらの種類の質問は、extension
を使用する回答を常に引き出します。単一のディクショナリまたは一度だけの特定の値のキーが必要であり、1回限りの場合に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)
}
}
これは、特定の値のキーが必要な場合に機能します。私の場合、最も簡単なアプローチでした。それが役立つことを願っています:
extension Dictionary where Key == String, Value: Equatable {
func key(for value: Value) -> Key? {
return compactMap { value == $1 ? $0 : nil }.first
}
}