在Swift中对searchBar结果进行过滤和排序

时间:2020-06-28 01:36:12

标签: ios arrays swift full-text-search uisearchbar

我正在尝试对我的项目进行搜索。我需要过滤变量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"

如何使这种排序成为可能?

1 个答案:

答案 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

}