Reputation: 1177
I need to change my search function from filtering an array:
func filterContentForSearchText(searchText: String, scope: String = "All") {
if searchText != "" {
filteredName = CGCoins.shared.ids.filter {name in
return name.lowercased().contains(searchText.lowercased())}
} else { filteredName = CGCoins.shared.ids
}
}
to filtering a Dictionary, which contains Symbols and their corresponding names. Ideally, I want to be able to search both the key and the value, for example, the dictionary, (CGCoins.shared.coinDictionary) looks like this:
["btc":"bitcoin","eth":"ethereum","ltc":"litecoin"...]
so I want to be able to search using UISearchBar and be able to search both "btc" and return "bitcoin" or search "bitcoin" and also return "bitcoin".
I have tried this:
func filterNewForSearchText(searchText: String, scope: String = "All") {
if searchText != "" {
filteredName = CGCoins.shared.coinDictionary.filter {name in
return name.key == searchText}
} else { filteredName = CGCoins.shared.coinDictionary.values
}
}
but I get the error:
Cannot assign value of type '[String : String]' to type '[String]'
How can I successfully filter the Dictionary, for both the key and value, and return the Value of whatever is searched? Any alternative solutions are also welcome.
Upvotes: 0
Views: 534
Reputation: 236340
Filtering a dictionary returns a tuple you need to map the result and return the dictionary values. In the else part you need to create a new array from its values:
func filterNewForSearchText(searchText: String, scope: String = "All") {
if !searchText.isEmpty {
filteredName = CGCoins.shared.coinDictionary
.filter {
$0.key == searchText
// if you need to search key and value and include partial matches
// $0.key.contains(searchText) || $0.value.contains(searchText)
// if you need to search caseInsensitively key and value and include partial matches
// $0.key.range(of: searchText, options: .caseInsensitive) != nil || $0.value.range(of: searchText, options: .caseInsensitive) != nil
}
.map{ $0.value }
} else {
filteredName = Array(CGCoins.shared.coinDictionary.values)
}
}
Upvotes: 5
Reputation: 18581
The error message comes from the fact that filtering a Dictionary won't return its values automatically, but you'll have to get its keys and then wrap them in an Array:
The following looks for an exact match in the keys, or if the searchText
is contained in values:
if searchText != "" {
filteredName = Array(CGCoins.shared.coinDictionary.filter {name in
return name.key == searchText || name.value.lowercased().contains(searchText.lowercased())
}.values)
} else {
filteredName = Array(CGCoins.shared.coinDictionary.values)
}
Upvotes: 0
Reputation: 3924
Try this one it's Working
For Like Query ( String contains another string )
let data = ["btc":"bitcoin","eth":"ethereum","ltc":"litecoin"]
let filtered = data.filter { $0.key.contains("c") || $0.value.contains("c") }
print(filtered) // ["btc":"bitcoin","ltc":"litecoin"]
For exact matching string
let filtered = data.filter { $0.key == "btc" || $0.value == "litecoin" }
Upvotes: 0