Поиск нескольких слов, игнорируя порядок в Swift 5 - PullRequest
0 голосов
/ 12 ноября 2019

В моем приложении я построил панель поиска, которая, для одного слова, работает отлично.

import Foundation

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()
}

С помощью приведенной выше функции, если я начну что-то печатать, это принесет все результаты, которые соответствуют критериям (если набранное слово найдено в Имени ИЛИ Специальности1 ИЛИ Специальности2).

Я сейчас началчтобы улучшить мой код и реализовать опцию, в которой пользователь может вводить слова в другом порядке, например: Имя SPACE specialty (1or2), specialty (1or2) SPACE Name и т. д., и приложение будет искать во всех 3 полях все введенные слова. Независимый от заказа.

Я нашел здесь что-то очень похожее на то, что я ищу, но я не мог спросить там, поскольку у меня репутация ниже 50 Поиск нескольких слов, игнорирующих порядок вSwift

Основное отличие от представленного решения состоит в том, что они используют базовый массив в примере

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

Это отличается от моего, основанного на Class Clinicнад. Я пытался адаптировать их код к своему случаю, как показано ниже

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) } }

Но я получаю несколько ошибок, таких как Значение типа «Клиника» не имеет элемента «нижний регистр» или Значение типа «Клиника» не имеет компонента «компоненты»'(есть и другие), которые я не знаю, как исправить.

Любая помощь очень ценится.

Спасибо

1 Ответ

1 голос
/ 12 ноября 2019

Вы можете попробовать

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
}
...