Ищете лучший способ отфильтровать текст из строки в Swift - PullRequest
0 голосов
/ 27 июня 2019

У меня есть массив строк в порядке сортировки по возрастанию. Я хочу отфильтровать символ / текст в этом массиве и получить результаты сначала из искомого текстового письма, а затем из остальных. Я ищу самый простой способ сделать эту работу. Пример:

Var array = ["Anand", "Ani", "Dan", "Eion", "Harsh", "Jocab", "Roshan", "Stewart"]

и текст для поиска "R"

Вывод должен быть:

Var outArray = ["Roshan", "Harsh", "Stewart"]

Ответы [ 4 ]

2 голосов
/ 27 июня 2019

Один из способов сделать это - сначала отобразить строки в кортеж, содержащий индекс искомого текста в строке и саму строку. Затем выполните сортировку по индексу, затем сопоставьте кортежи со строками.

let array = ["Anand", "Ani", "Dan", "Eion", "Harsh", "Jocab", "Roshan", "Stewart"]
let searchText = "R"
// compactMap acts as a filter, removing the strings where string.index(of: searchText, options: [.caseInsensitive]) returns nil
let result = array.compactMap { string in string.index(of: searchText, options: [.caseInsensitive]).map { ($0, string) } }
                    .sorted { $0.0 < $1.0 }.map { $0.1 }

Метод index(of:options:) взят из этого ответа здесь .

Для Swift 4.x:

extension StringProtocol where Index == String.Index {
    func index(of string: Self, options: String.CompareOptions = []) -> Index? {
        return range(of: string, options: options)?.lowerBound
    }
    func endIndex(of string: Self, options: String.CompareOptions = []) -> Index? {
        return range(of: string, options: options)?.upperBound
    }
    func indexes(of string: Self, options: String.CompareOptions = []) -> [Index] {
        var result: [Index] = []
        var startIndex = self.startIndex
        while startIndex < endIndex,
            let range = self[startIndex...].range(of: string, options: options) {
                result.append(range.lowerBound)
                startIndex = range.lowerBound < range.upperBound ? range.upperBound :
                    index(range.lowerBound, offsetBy: 1, limitedBy: endIndex) ?? endIndex
        }
        return result
    }
    func ranges(of string: Self, options: String.CompareOptions = []) -> [Range<Index>] {
        var result: [Range<Index>] = []
        var startIndex = self.startIndex
        while startIndex < endIndex,
            let range = self[startIndex...].range(of: string, options: options) {
                result.append(range)
                startIndex = range.lowerBound < range.upperBound ? range.upperBound :
                    index(range.lowerBound, offsetBy: 1, limitedBy: endIndex) ?? endIndex
        }
        return result
    }
}
1 голос
/ 27 июня 2019

Используйте filter на array, чтобы отфильтровать все Strings, которые содержат searchText, то есть

let array = ["Anand", "Ani", "Dan", "Eion", "Harsh", "Jocab", "Roshan", "Stewart"]
let searchText = "R"
let filteredArray = array.filter({$0.lowercased().contains(searchText.lowercased())})
let sortedArray = filteredArray.sorted { (str1, str2) -> Bool in
    if let index1 = str1.lowercased().firstIndex(of: Character(searchText.lowercased())), let index2 = str2.lowercased().firstIndex(of: Character(searchText.lowercased())) {
        return index1 < index2
    }
    return false
}
print(sortedArray) //["Roshan", "Harsh", "Stewart"]
0 голосов
/ 27 июня 2019
let words = ["Anand", "Ani", "Dan", "Eion", "Harsh", "Jocab", "Roshan", "Stewart"]
let keyword = "r"
let result = words.filter { $0.contains(keyword) }
    .sorted { ($0.hasPrefix(keyword) ? 0 : 1) < ($1.hasPrefix(keyword) ? 0 : 1) }
0 голосов
/ 27 июня 2019

Попробуйте это


 if searchText.!characters.isEmpty
 {
      for strSearch in filterArray
      {
           let range = strSearch.lowercased().range(of: searchText, options: .caseInsensitive, range: nil,   locale: nil)

           if range != nil
            {
               searchedArray.append(strSearch)
            }
        }
     } 
  else 
  {
      searchedArray = filterArray
  }

...