Search multiple words in one string in swift
If you are looking for less code:
let text = "Hello Swift-world"
let wordList = ["Hello", "world"]
let success = !wordList.contains(where: { !text.contains($0) })
print(success)
It is also a little more efficient than your solution because
the contains
method returns as soon as a "not contained" word
is found.
As of Swift 4 or later, you can use allSatisfy
:
let success = wordList.allSatisfy(text.contains)
Search for multiple words ignoring the order in Swift 5
You can try
let searArr = searchText.lowercased().components(separatedBy: " ")
clinicsSearch = clinics.filter { item in
let res = searArr.filter { item.name.lowercased().contains($0) ||
item.specialty1.lowercased().contains($0) ||
item.specialty2.lowercased().contains($0)
}
return !res.isEmpty
}
It could be better to do
let searArr = searchText.lowercased().components(separatedBy: " ")
clinicsSearch = clinics.filter { item in
let lowName = item.name.lowercased()
let lowSp1 = item.specialty1.lowercased()
let lowSp2 = item.specialty2.lowercased()
let res = searArr.filter {
lowName.contains($0) ||
lowSp1.contains($0) ||
lowSp2.contains($0)
}
return !res.isEmpty
}
Search Multiple Words (or Characters) in String Array (swift)
There's a swifty way to solve your problem
I started with using just one filter on the myArr array using hardcoded search terms
let filteredStrings : [String] = myArr.filter({
return $0.contains("I") && $0.contains("N")
})
but thats going to help only if your findChars are always going to be I and N only.
Later I realized how to do it without hardcoding the find char characters:
ANSWER 1
let myArr: [String] = ["BERLIN","ISTANBUL","TOKYO","NEWYORK","PRAGUE","WIEN"]
let findChrs = ["I","N"]
let filteredStrings : [String] = myArr.filter({ (aString) in
let hasChars = findChrs.filter({(bString) in
return aString.contains(bString)
})
print(hasChars)
return hasChars.count == findChrs.count
})
print(filteredStrings)
Instead of using $0, I think in the second chunk of code, its easier to understand whats happening with aString
and bString
.
Do check the code in a playground and see how this code works. If you haven't used the higher order functions, it can be a little daunting to understand filters without a playground and the print statements.
Update:
Was just thinking about this problem and I gave this alternate approach a try, using sets, map and filter. It is super swifty, and can be difficult to read/understand:
ANSWER 2, concise
let myArr: [String] = ["BERLIN","ISTANBUL","TOKYO","NEWYORK","PRAGUE","WIEN"]
let findChrs = ["I","N"]
let finderSet:Set<String> = Set(findChrs)
let filteredArray = myArr.filter {
return Set($0.characters.map({String($0)})).intersection(finderSet).count == findChrs.count
}
For the sake of readability and ease of understanding, here's what is happening:
Answer 2, verbose
let filteredArray = myArr.filter { (aString) -> Bool in
//for each string in myArr, convert it into an array of string chars
let stringArray = aString.characters.map({aCharacter in
String(aCharacter)
})
//convert string array into a set
let aSet = Set(stringArray)
// find the intersection (common elemnts from aSet and finderSet)
let intersect = aSet.intersection(finderSet)
//return true if aString has all of findChrs elements
return intersect.count == findChrs.count
}
Both Answer 2 'concise' and 'verbose' will give you the same results.
Based on some simple code execution time check, it looks like Answer 1 is ~3x faster than Answer 2. So, Answer 1 is still a better choice and probably easier to understand.
Hope this helps anyone reading the answer understand filter and map!
Search for multiple words ignoring the order in Swift
Just filter elements from filterArray
which contains both of these words
let filterArray = ["Big green bubble", "Red bubble", "A bubble in green", "Small green bubble", "This bubble is green"]
let textString = "green bubble".lowercased()
let words = textString.components(separatedBy: " ")
let results = filterArray.map { $0.lowercased() }.filter { string in words.allSatisfy { string.components(separatedBy: " ").contains($0) } }
print(results) /* ["Big green bubble", "A bubble in green", "Small green bubble", "This bubble is green"] */
Filter search on multiple words, iOS, Swift
Using this you can also achieve a search with inverse order ("Blue Ball" -> "Ball Blue").
let splitText = searchText.split(separator: " ")
let filteredObjects = objects.filter {
var include = false
for text in splitText {
if let s = $0["object"], text.contains(s) {
include = true
continue
}
if let s = $0["color"], text.contains(s) {
include = true
continue
}
return false
}
return include
}
UISearchBar use multiple words for different values, iOS, Swift
By splitting the search text using space and search all the elements in all the posts to filter.
let splitText = text.split(separator: " ")
let filteredData = posts.filter {
if let s = $0["shape"] as? String, splitText.index(of: Substring(s)) != nil {
return true
}
if let s = $0["color"] as? String, splitText.index(of: Substring(s)) != nil {
return true
}
return false
}
And as all other mentioned you should use String
in swift not NSString
.
Search string for multiple substrings in iOS Swift
You should use a for-loop.
for ingredient in ["salt", "pepper"] {
if ingredientList.rangeOfString(ingredient) != nil {
print("\(ingredient) found")
}
}
Even better, add this for-loop as an extension to the String class.
extension String {
func findOccurrencesOf(items: [String]) -> [String] {
var occurrences: [String] = []
for item in items {
if self.rangeOfString(item) != nil {
occurrences.append(item)
}
}
return occurrences
}
}
Then you can get the occurrences like this:
var items = igredientList.findOccurrencesOf(["salt", "pepper"])
Swift: How to filter UISearchBar for multiple strings?
I did find a solution, sure it's not the best in case of performance, but you can go from here and improve my answer.
I test it in Playground
, i did leave some comments, if you need more information let me know, here is a simple code:
import Foundation
struct SearchItem {
let title: String
let subtitle: String
}
/// Trim white spaces from start and end, and map all words to lowercase
let searchedWords = "Bob man woman"
.trimmingCharacters(in: .whitespacesAndNewlines)
.components(separatedBy: " ")
.map { $0.lowercased() }
let itemArray: [SearchItem] = [
SearchItem(title: "Bob", subtitle: "Woman"),
SearchItem(title: "Joe", subtitle: "Man"),
SearchItem(title: "Bob", subtitle: "Man")
]
/// Lowercase all itemArray
let lowercasedItems = itemArray
.map { SearchItem(title: $0.title.lowercased(), subtitle: $0.subtitle.lowercased()) }
/// First trying to find best result which is contains both `title` and `subtitle`
var filteredArray = lowercasedItems
.filter { searchedWords.contains($0.title) && searchedWords.contains($0.subtitle) }
/// `filteredArray.isEmpty == false`, then we didn't find best result which contains both `title` and `subtitle`
/// `filteredArray.isEmpty == true` then we'll try to find at least one match
if filteredArray.isEmpty {
filteredArray = lowercasedItems
.filter { searchedWords.contains($0.title) || searchedWords.contains($0.subtitle) }
}
print(searchedWords)
print(filteredArray)
Hope this will help you!
Related Topics
Swift Convert Decimal Coordinate into Degrees, Minutes, Seconds, Direction
Swiftui Hstack with Equal Height
Firebase Auth Internal Error on Login Attempt
How to Record My MAC's Internal Sound, Not the Microphone!, Using Avcapturesession
Converting Audiobuffer to Cmsamplebuffer with Accurate Cmtime
How to Process an Array of Task Asynchronously with Swift Combine
How to Make Player Move to Opposite Side While Is in a Path
How to Migrate Core Data's Data to App Group's Data
Why It Is Called the Memberwise Initialiser
Get Color of Point in a Skscene Swift
Properly Using Firebase Cloud Functions and Stripe
Closure Use of Non-Escaping Parameter - Swift 3 Issue
Can a Subclass Override a Function and Make More Restrictive Return
How to Call a Generic Swift Function When None of the Arguments Provides the Generic Type
Subscript of a Struct Doesn't Set Values When Created as an Implicitly Unwrapped Optional