搜索UITableView并忽略标点符号

时间:2016-12-19 22:47:19

标签: ios swift string uitableview uisearchcontroller

有没有办法搜索UITableView并忽略某些字符,如逗号或点?

即。我想搜索“St George”,但我的数据集包含“St. George”,因此结果始终为零。

已编辑问:

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

2 个答案:

答案 0 :(得分:1)

在执行搜索之前,您可以过滤掉字符串中没有字母的所有字符。这同样适用于表视图数据源元素。同样如rmaddy所述,您应该实现不区分大小写的搜索:

extension UnicodeScalar {
    init?(_ character: Character) {
        self.init(character.string)
    }
}
extension Character {
    var unicodeScalar: UnicodeScalar? {
        return UnicodeScalar(self)
    }
    var string: String {
        return String(self)
    }
}
extension Sequence where Element == Unicode.Scalar {
    var view: String.UnicodeScalarView {
        return String.UnicodeScalarView(self)
    }
}
extension String.UnicodeScalarView {
    var string: String {
        return String(self)
    }
}
extension StringProtocol where Index == String.Index {
    func containsCaseInsensitive(_ string: String) -> Bool {
        return range(of: string, options: .caseInsensitive) != nil
    }
    var letters: String {
        return unicodeScalars.filter(CharacterSet.letters.contains).view.string
    }

}

测试:

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

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

如果你想从字符串中删除标点符号(注意这会保留字符串中的空格),你可以按照以下步骤操作:

extension String {
    var removingPunctuation: String {
        return String(characters.filter {
             guard let unicodeScalar = $0.unicodeScalar else { return true }
             return !CharacterSet.punctuationCharacters.contains(unicodeScalar)
        })
    }
}

测试:

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

如果你想实现与Xcode自动完成相同的逻辑,你需要搜索每个字符并更改搜索字符串的startIndex:

extension String {
    func containsCaseInsensitiveCharactersInSequence(_ string: String) -> Bool {
        var found = 0
        var start = startIndex
        string.characters.forEach {
            while let range = range(of: String($0), options: .caseInsensitive, range: start..<endIndex) {
                found += 1
                start = range.upperBound
                break
            }
        }
        return found == string.characters.count
    }
}

游乐场测试:

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

let filtered = tableViewSource.filter {

    $0.removingPunctuation.containsCaseInsensitiveCharactersInSequence(search.removingPunctuation)

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

答案 1 :(得分:0)

我认为你应该简单地实现一个函数,对于任何给定的字符串,将返回相同的字符串而没有任何点,(或者你想要删除的任何内容);如:

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
 }

(我无法从我的位置测试它,但你明白了吗?)

希望有所帮助