Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find one key containing string in swift dictionary

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...

like image 305
Adeline Avatar asked Jul 31 '16 12:07

Adeline


2 Answers

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
}
like image 192
Martin R Avatar answered Oct 01 '22 12:10

Martin R


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"
like image 26
vacawama Avatar answered Oct 01 '22 13:10

vacawama