Searching a UITableView and ignoring punctuation

一笑奈何 提交于 2019-12-06 16:26:33

问题


Is there a way to search through a UITableView and ignore certain characters like commas or dots?

I.e. I would like to search for "St George" but my data set contains "St. George" so the result is always zero.

EDITED Q:

 func filteredArray(searchText: NSString) {
    if searchText == "" {
        array_search = array_all
    } else {
        showTableViewResults()
        array_search.removeAll()
        for i in 0 ..< array_all.count {
            let object:MyObject = array_all[i]
            let languageSearchString = object.myObjectName
            let searchStr:String = languageSearchString!
            if searchStr.lowercased().contains(searchText.lowercased) {
                array_search.append(object)
            }
        }
    }
    tableView.reloadData()
    recordsFoundLabel.text = "records found: \(array_search.count)"
}

回答1:


You can filter all characters thats not a letter out of your String before performing your search. The same applies to the table view data source elements. Also as mentioned by rmaddy you should implement a case insensitive search:

edit/update Swift 5 or later

extension StringProtocol where Self: RangeReplaceableCollection {
    func containsCaseInsensitive(_ string: String) -> Bool {
        return range(of: string, options: .caseInsensitive) != nil
    }
    var letters: Self {
        return filter{ $0.isLetter }
    }
}

Testing:

let search = "st george"
let tableViewSource = ["Apple", "Orange", "Banana", "St. George"]

let filtered = tableViewSource.filter {
    $0.letters.containsCaseInsensitive(search.letters)
}
print(filtered)   // ["St. George"]


If you would like to literally just remove punctuation from your String (note that would keep the spaces in your String), you can do as follow:

extension StringProtocol where Self: RangeReplaceableCollection {
    mutating func removePunctuation() {
        removeAll { !$0.isPunctuation }
    }
    var removingPunctuation: Self {
        return filter { !$0.isPunctuation }
    }
}

Testing:

let filtered = tableViewSource.filter {
    $0.removingPunctuation.caseInsensitiveContains(search.removingPunctuation)
}
print(filtered)   // ["St. George"]

If you would like to implement the same logic as Xcode autocomplete you would need to do a search for each character and change the startIndex of the string searched:

extension StringProtocol where Self: RangeReplaceableCollection {
    func containsCaseInsensitiveCharactersInSequence(_ string: Self) -> Bool {
        var found = 0
        var start = startIndex
        string.forEach {
            while let range = self[start...].range(of: String($0), options: .caseInsensitive) {
                found += 1
                start = range.upperBound
                break
            }
        }
        return found == string.count
    }
}

Playground Testing:

let search = "stgrge"
let tableViewSource = ["Apple", "Orange", "Banana", "St. George"]

let filtered = tableViewSource.filter {

    $0.removingPunctuation.containsCaseInsensitiveCharactersInSequence(search.removingPunctuation)

}
print(filtered)   // ["St. George"]



回答2:


I think you should simply implement a function that for any given string, will return te same string without any point, (or whatever you want to erase); such as :

func erase(characters: [String], fromText text: String) -> String {
    var result = String()
    for character in text.characters {
         if !characters.contains(character) {
             result += String(character)
         }
    }
    return result
 }

(I cant test it from where i am but you get the idea right ?)

Hope it helps



来源:https://stackoverflow.com/questions/41232236/searching-a-uitableview-and-ignoring-punctuation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!