CodeBender
CodeBender

Reputation: 36640

How to determine if 2 or more words are contained within a variety of strings

I have a situation where a value contains multiple fields, and provide a search bar where a user may enter phrases that could be split between those fields.

The following is a short sample from a playground illustrating what I would like to accomplish.

import Foundation

struct Item {
    let name: String
    let size: String
}
let itemA = Item(name: "stuff", size: "Large")
let itemB = Item(name: "something", size: "X-Large")
let items = [itemA, itemB]

let singleSearch = "stuff"
let singleFound = items.filter { $0.name.localizedStandardContains(singleSearch) ||
    $0.size.localizedStandardContains(singleSearch)
}
print(singleFound) // ItemA

let multiSearch = "stuff large"
let multiFound = items.filter { $0.name.localizedStandardContains(multiSearch) ||
    $0.size.localizedStandardContains(multiSearch)
}

print(multiFound) // Nothing found, expect to see itemA

Also, it has to be able to handle partial words as a user searches, to support winnowing down visible options.

let partialSearch = "stuff l"
let partialFound = items.filter { $0.name.localizedStandardContains(partialSearch) ||
    $0.size.localizedStandardContains(partialSearch)
}

print(partialFound) // Nothing found, expect to see itemA

I suspect I may need to split the search term up into an array and process each word individually and see what the result is from the combined check. My concern is that the actual implementation has far more fields, so this could be impractical.

Upvotes: 0

Views: 63

Answers (1)

arturdev
arturdev

Reputation: 11039

As a fast solution you can do following:

let multiSearch = "st la"
let trimmed = multiSearch.trimmingCharacters(in: .whitespacesAndNewlines)
let multiSearchComponents = trimmed.components(separatedBy: " ")

var filtered = items
multiSearchComponents.forEach { searchTerm in
    filtered = filtered.filter { item in
        item.name.localizedStandardContains(searchTerm) || item.size.localizedStandardContains(searchTerm)
    }
}

print(filtered) //Prints itemA

Upvotes: 1

Related Questions