1

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

 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

4

3 回答 3

1

作为对@appzYourLife 解决方案的改进,您可以使用本机 Swift 执行此操作Set,因为在这种情况下不一定需要计数集。这将省去map(_:)每个名字的字符并将它们桥接到Objective-C。您现在可以只使用一组Characters,因为它们是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(_:_:)andflatMap(_:)来过滤掉对应的糖果。

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()
}
于 2016-08-14T10:02:28.690 回答
0

Swift 3代码更新:

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

  tableView.reloadData()
}
于 2017-02-20T12:56:41.720 回答
0

首先是这样的代码块

if someCondition == true {
   return true
} else {
   return false
}

也可以这样写

return someCondition

正确的?:)

重构

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

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

加扰搜索

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

为此,我们需要 Swift 3 提供的 CountedSet。由于您使用的是 Swift 2.2,我们将使用旧的 NSCountedSet,但需要一些与 Objective-C 的桥接。

这是代码。

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()
}
于 2016-08-13T23:21:54.687 回答