如何查找字符串是否包含字符串的所有字符,以便在Swift中进行实时搜索?

时间:2016-08-13 22:37:17

标签: swift livesearch

我试图在我的应用中实现我正在制作的搜索。我有一个我试图搜索的数组,我在网上找到了这个代码:

 func filterContentForSearchText(searchText: String) {
        filteredCandies = candies.filter({( candy : Candies) -> Bool in
        if         candy.name.lowercaseString.containsString(searchText.lowercaseString) == true  {
            return true
        } else {
            return false
        }
    })
    tableView.reloadData()
}

问题在于,我试图实现搜索的数据库中的文本都是乱码的,因为它应该缩短。如何进行搜索以检查是否所有字母都在那里而不是正确搜索正确的名称。来自数据库(USDA)的对象示例:CRAB,DUNGINESS,RAW 如果您有答案,请快速进行实时搜索。非现场搜索让搜索变得很糟糕(至少对我而言)!

我使用的是Swift 2.2和Xcode 7

3 个答案:

答案 0 :(得分:1)

作为对@appzYourLife's solution的改进,您可以使用原生Swift Set执行此操作,因为在这种情况下不一定需要计数集。这将节省每个名称的字符map(_:)并将它们连接到Objective-C。您现在可以使用一组Character,因为他们是Hashable

例如:

struct Candy {
    let name: String
}

let candies = [Candy(name: "CRAB"), Candy(name: "DUNGINESS"), Candy(name: "RAW")]    
var filteredCandies = [Candy]()

func filterContentForSearchText(searchText: String) {
    let searchCharacters = Set(searchText.lowercaseString.characters)
    filteredCandies = candies.filter {Set($0.name.lowercaseString.characters).isSupersetOf(searchCharacters)}
    tableView.reloadData()
}

filterContentForSearchText("RA")
print(filteredCandies) // [Candy(name: "CRAB"), Candy(name: "RAW")]

filterContentForSearchText("ED")
print(filteredCandies) // Candy(name: "DUNGINESS")]

此外,取决于您是否可以将此识别为性能瓶颈(您应首先进行一些分析) - 您可以通过缓存包含“糖果”字符的集合来进一步优化上述内容。名称,无需在每次搜索时重新创建它们(尽管如果您更新candies数据,则必须确保它们已更新)。

当您来搜索时,您可以使用zip(_:_:)flatMap(_:)来过滤掉相应的糖果。

let candies = [Candy(name: "CRAB"), Candy(name: "DUNGINESS"), Candy(name: "RAW")]

// cached sets of (lowercased) candy name characters
let candyNameCharacterSets = candies.map {Set($0.name.lowercaseString.characters)}

var filteredCandies = [Candy]()

func filterContentForSearchText(searchText: String) {
    let searchCharacters = Set(searchText.lowercaseString.characters)
    filteredCandies = zip(candyNameCharacterSets, candies).flatMap {$0.isSupersetOf(searchCharacters) ? $1 : nil}
    tableView.reloadData()
}

答案 1 :(得分:0)

首先是像这样的代码块

return someCondition

也可以这样写出来

func filterContentForSearchText(searchText: String) {
    filteredCandies = candies.filter { $0.name.lowercaseString.containsString(searchText.lowercaseString) }
    tableView.reloadData()
}

正确? :)

重构

所以你的原始代码看起来像这样

struct Candy {
    let name: String
}


let candies = [Candy]()
var filteredCandies = [Candy]()

func filterContentForSearchText(searchText: String) {

    let keywordChars = NSCountedSet(array:Array(searchText.lowercaseString.characters).map { String($0) })

    filteredCandies = candies.filter {
        let candyChars = NSCountedSet(array:Array($0.name.lowercaseString.characters).map { String($0) }) as Set<NSObject>
        return keywordChars.isSubsetOfSet(candyChars)
    }

    tableView.reloadData()
}

加扰搜索

现在,给定一个字符串A,你想知道另一个字符串B是否包含A的所有字符吗?

为此,我们需要可从Swift 3获得的CountedSet。由于您使用的是Swift 2.2,我们将使用旧的NSCountedSet,但需要对Objective-C进行一些桥接。

这是代码。

new

答案 2 :(得分:0)

Swift 3 代码更新:

func filterContentForSearchText(searchText: String, scope: String = "All") {
  filteredCandies = candies.filter { candy in
    return candy.name.localizedLowercase.contains(searchText.lowercased())
  }

  tableView.reloadData()
}