I have created an array struct to house my values used in a list. Now I want to be able to search this list and every time the user makes a blank space it should be viewed by the program as two different searchwords that should both be met. I have successfully created a function to get the searchwords but I don't really get how to now filter my stuctArray by all the searchWords.
let searchWords = findAllSearchResutsRecursive(searchWord) //example ["A", "B", ,"C"]
let filteredArray = listArray.filter {
for word in searchWords {
$0.firstname!.capitalized.contains(word.capitalized) ||
$0.lastname!.capitalized.contains(word.capitalized) ||
$0.id!.capitalized.contains(word.capitalized) ||
$0.city!.capitalized.contains(word.capitalized)
}
}
To clarify, if the searchWords is ["A", "N"] and one of the participants (people in the list) has the firstname "Anna" but nothing else match the search I still want to show it.
Alternatively is if it would be better to convert the SearchWords
to a set and in that way somehow filter them all at the same time.
CodePudding user response:
You could use the reduce method to check if any of the search words are present in the struct's properties. Here's an example of how you could implement this:
let filteredArray = listArray.filter {
searchWords.reduce(false) {
$0 ||
$1.capitalized.contains($1.firstname!.capitalized) ||
$1.capitalized.contains($1.lastname!.capitalized) ||
$1.capitalized.contains($1.id!.capitalized) ||
$1.capitalized.contains($1.city!.capitalized)
}
}
The reduce method takes an initial value and a closure that takes the current result and the next element from the array, and it returns the final result. In this case, it starts with false
as the initial value and checks if any of the search words are present in the struct's properties.
CodePudding user response:
You could rewrite it like this:
let searchWords = findAllSearchResutsRecursive(searchWord) //example ["A", "B", ,"C"]
let filteredArray = listArray.filter {
var matchFound = false
for word in searchWords {
if (
$0.firstname!.capitalized.contains(word.capitalized) ||
$0.lastname!.capitalized.contains(word.capitalized) ||
$0.id!.capitalized.contains(word.capitalized) ||
$0.city!.capitalized.contains(word.capitalized)
) {
matchFound = true
}
}
return matchFound
}
CodePudding user response:
The outer filter function needs to return a boolean value. To not iterate over all remaining words if a match is found you could use:
let filteredArray = listArray.filter {
var result = false
for word in searchWords {
// check if any property contains the word
if $0.firstname!.capitalized.contains(word.capitalized) ||
$0.lastname!.capitalized.contains(word.capitalized) ||
$0.id!.capitalized.contains(word.capitalized) ||
$0.city!.capitalized.contains(word.capitalized){
// set the result and break the loop
result = true
break
}
}
// return the result
return result
}