Home > Net >  Swift filter a array struct by an array of search words
Swift filter a array struct by an array of search words

Time:01-19

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.

This is errors I get: enter image description here

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
}
  • Related