I have a [String:String]
dictionary. I would like to get the value associated with any key containing the string "S". Order does not matter.
This is dead easy : just get all the keys, iterate, return the first matching the condition.
HOWEVER, I would like to do that using a swift-like elegant approach. Something using a filter
or map
functions. And that's where I get lost...
Since you are only interested in any matching value,
you can use the indexOf()
method to find the first matching
dictionary entry. This works because
a dictionary is a collection of key/value pairs.
Swift 2:
let dict = ["foo": "bar", "PQRS": "baz"]
let searchTerm = "S"
if let index = dict.indexOf({ (key, _) in key.containsString(searchTerm) }) {
let value = dict[index].1
print(value)
} else {
print("no match")
}
As soon as a matching key is found, the predicate returns true
and the enumeration stops. The index
is a "dictionary index" which
can be used directly to get the corresponding dictionary entry.
For a case-insensitive key search, replace the predicate by
{
(key, _) in key.rangeOfString(searchTerm, options: .CaseInsensitiveSearch) != nil
}
In Swift 3 you can use first(where:)
to find the first matching
element, this saves one dictionary lookup:
if let entry = dict.first(where: { (key, _) in key.contains(searchTerm) }) {
print(entry.value)
} else {
print("no match")
}
For a case-insensitive key search, replace the predicate by
{
(key, _) in key.range(of: searchTerm, options: .caseInsensitive) != nil
}
You can do it with flatMap
and containsString
:
Swift 2.x:
let dict = ["one": "1", "two": "2", "three": "3", "four": "4", "five": "5", "six": "6"]
let results = dict.flatMap { (key, value) in key.lowercaseString.containsString("o") ? value : nil }
print(results)
Output:
["4", "1", "2"]
print(results.first ?? "Not found")
4
Or if you love cryptic one liners:
let first = dict.flatMap { $0.lowercaseString.containsString("o") ? $1 : nil }.first ?? "Not found"
For Swift 3:
let dict = ["one": "1", "two": "2", "three": "3", "four": "4", "five": "5", "six": "6"]
let results = dict.flatMap { (key, value) in key.lowercased().contains("o") ? value : nil }
print(results)
print(results.first ?? "Not Found")
Or if you love cryptic one liners:
let first = dict.flatMap { $0.lowercased().contains("o") ? $1 : nil }.first ?? "Not Found"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With