我正在尝试对我的项目进行搜索。我需要过滤变量yarn --version
并填充到数组yarn --check-for-updates
中。 productTagsArray
是用户在searchBar中键入的内容。这是我必须过滤的代码:
allProductSearchResults
上面的代码可以正常工作;但是,变量searchText
的最终结果未排序。我需要根据var allProductSearchResults: [[String : [String]]] = [[:]]
var productTagsArray : [[String : [String]]] = [[:]]
func filterContent(for SearchText: String){
allProductSearchResults = productTagsArray.filter({ (productTagsArray) -> Bool in
for product in productTagsArray {
if let tags = product.value as? [String] {
for tag in tags {
let searchTextArr = SearchText.split {$0 == " "}
let searchX = searchTextArr.flatMap { $0.lowercased().components(separatedBy: " ")}
let tagLowerCase = tag.lowercased().replacingOccurrences(of: ",", with: " ")
let isMatch = searchX.filter { tagLowerCase.range(of:$0) != nil }.count != 0
return isMatch
}
}
return false
}
return false
})
}
和allProductSearchResults
之间匹配的单词数对结果进行排序。例如,如果有人搜索tag
searchText
以及在productTagsArray中(如果我有以下产品):
organic green kale
一旦使用上面的代码完成了过滤器,我想确保它是根据searchText和标记之间的匹配进行排序的,因此它将按照以下顺序进行:
searchText = "organic green kale"
如何使这种排序成为可能?
答案 0 :(得分:0)
与其进行筛选(该筛选仅删除不匹配的产品),不如将map
放入一个具有匹配数量并与该产品一起计数的元组中,然后filter
淘汰那些0个匹配项,进行排序,然后map
回到产品中。
func filterContent(for searchText: String) -> [[String : [String]]] {
let searchTokens = searchText.split(" ")
return productTagsArray.map { productTags -> ([String: [String]], Int) in
var matches = 0
for (_, tags) in productTags {
for searchToken in searchTokens {
// sum up the matches that of this search token
matches += tags.reduce(0, {
$0 + ($1.localizedCaseInsensitiveContains(searchToken) ? 1 : 0) })
}
}
return (productTags, matches) // <-- return product with # of matches
}
.filter({ $0.1 > 0 }) // <-- filter out zero matches
.sorted(by: { $0.1 > $1.1 }) // <-- sort by matches
.map { $0.0 } // <-- map back to productTags
}