【发布时间】:2014-11-30 21:51:26
【问题描述】:
我正在使用 [UIImage:UIImage] 类型的 swift 字典,并且我正在尝试为给定值查找特定键。在 Objective-C 中,我可以使用 allKeysForValue,但 Swift 字典似乎没有这样的方法。我应该使用什么?
【问题讨论】:
标签: swift dictionary
我正在使用 [UIImage:UIImage] 类型的 swift 字典,并且我正在尝试为给定值查找特定键。在 Objective-C 中,我可以使用 allKeysForValue,但 Swift 字典似乎没有这样的方法。我应该使用什么?
【问题讨论】:
标签: swift dictionary
如果反向字典查找用例涵盖键和值之间具有一对一关系的双射字典,则收集穷举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
【讨论】:
据我所知,没有内置的 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 开始,现在可以实现 具有等值字典的扩展方法 (感谢Airspeed Velocity 让我在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]
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]
【讨论】:
allKeys(forValue:) 也是正确的。具有类似命名的现有方法是index(forKey:)、update(value: forKey)、value(forKey:)。
如果您转换为NSDictionary,则可以使用allKeys(for:):
let keys = (dict as NSDictionary).allKeys(for: image) as! [UIImage]
【讨论】:
let keys = (ItemDict as NSDictionary).allKeysForObject(orderItems[indexPath.row]) 然后你可以访问:let someIntValue = keys[0].integerValue; 像梦一样工作,谢谢!跨度>
let keys = (dict as NSDictionary).allKeys(for: image) as! [UIImage]
了解这些答案中的大多数会在搜索字典之前获取字典的整个键集。此答案使用找到密钥后返回的first(where:) 方法。
Swift 5(内联)
let someValue = UIImage()
if let key = someDictionary.first(where: { $0.value == someValue })?.key {
print(key)
}
Swift 5(扩展)
extension Dictionary where Value: Equatable {
func key(from value: Value) -> Key? {
return self.first(where: { $0.value == value })?.key
}
}
print(someDictionary.key(from: someValue)) // optional
if let key = someDictionary.key(from: someValue) {
print(key) // non-optional
}
【讨论】:
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
【讨论】:
这是另一种方法,我写了关于on my blog。它针对 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。如果您有兴趣,我在我的Higher-order functions in Swift 文章中写过flatMap。
另外,因为我的方法是通用的(由于在Dictionary<Key,Value> 通用类中),您不需要将其结果转换为键的类型,这在使用NSDictionary 中的allKeysForObject(_:) 时是必需的。
【讨论】:
Swift 2 版本:
func allKeysForValue<K, V : Equatable>(dict: [K : V], val: V) -> [K] {
return dict.filter{ $0.1 == val }.map{ $0.0 }
}
【讨论】:
$0.1 和$0.0 而不是$0 和$1?
key 和value 是字典元素,对吧?因为dictionary = [key:valule].
$0 是字典中的第一个元素吗?喜欢[firstKey:firstValue]?
如果您需要为一个值找到 some 键(即,如果有多个,则不是 all,而是任意一个):
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 返回nil。
【讨论】:
如果您需要特定值的任何键,这将起作用。在我的情况下是最简单的方法。希望对你有帮助:
extension Dictionary where Key == String, Value: Equatable {
func key(for value: Value) -> Key? {
return compactMap { value == $1 ? $0 : nil }.first
}
}
【讨论】:
如果您不知道这些值是唯一的,这是一个选项:
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: "?"),
"?"
)
【讨论】: