Search Multiple Words in One String in Swift

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



Leave a reply



Submit