首页 > 解决方案 > 在 Swift 5 中搜索多个单词忽略顺序

问题描述

在我的应用程序中,我构建了一个 SearchBar,对于一个单词,它工作得非常好。

进口基金会

class Clinic {
    var id = ""
    var name = ""
    var address = ""
    var specialty1 = ""
    var specialty2 = ""
}

在我的 textDidChange 我有

var clinics: [Clinic] = [] // Clinics Data Structure
var clinicsSearch: [Clinic] = [] // Filtered Clinics

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {

    // works for one word (either in name or specialty1 or specialty2)
    clinicsSearch = clinics.filter { $0.name.lowercased().contains(searchText.lowercased()) ||
        $0.specialty1.lowercased().contains(searchText.lowercased()) ||
        $0.specialty2.lowercased().contains(searchText.lowercased())
    }
    searching = true
    tableView.reloadData()
}

使用上面的 func,如果我开始输入内容,它将带来所有符合条件的结果(如果输入的单词在 Name OR Specialty1 OR Specialty2 中找到)。

我现在开始寻求改进我的代码并希望实现一个选项,用户可以按不同的顺序键入单词,例如:名称空间专业(1or2),专业(1or2)空间名称等,应用程序将搜索所有 3 个字段键入的单词。订单独立。

我在这里找到了与我正在寻找的非常相似的东西,但我无法在那里询问,因为我的声誉低于 50 搜索多个单词忽略 Swift 中的顺序

与那里提出的解决方案的主要区别在于它们在示例中使用基本的数组

let filterArray = ["Big green bubble", "Red bubble", "A bubble in green", "Small green bubble", "This bubble is green"]

这与我的不同,它基于上面的班级诊所。我试图使他们的代码适应我的情况,如下所示

let textString = searchText.lowercased()
let words = textString.components(separatedBy: " ")
clinicsSearch = clinics.map { $0.name.lowercased() }.filter { string in words.allSatisfy { string.components(separatedBy: " ").contains($0) } }

但是我遇到了几个错误,例如“诊所”类型的值没有“小写”成员或“诊所”类型的值没有成员“组件”(还有其他人),我不知道如何解决。

任何帮助是极大的赞赏。

谢谢

标签: arraysswiftfilteruisearchbar

解决方案


你可以试试

let searArr = searchText.lowercased().components(separatedBy: " ")
clinicsSearch = clinics.filter { item in
                                  let res  = searArr.filter { item.name.lowercased().contains($0) ||    
                                  item.specialty1.lowercased().contains($0) || 
                                  item.specialty2.lowercased().contains($0) 
                }
   return !res.isEmpty
}

这样做可能会更好

let searArr = searchText.lowercased().components(separatedBy: " ")
clinicsSearch = clinics.filter { item in
         let lowName = item.name.lowercased()
         let lowSp1 = item.specialty1.lowercased()
         let lowSp2 = item.specialty2.lowercased()
         let res  = searArr.filter {
                      lowName.contains($0) ||    
                      lowSp1.contains($0) || 
                      lowSp2.contains($0) 
         }
   return !res.isEmpty
}

推荐阅读