菜鸟教程小白 发表于 2022-12-11 18:26:34

ios - Swift - 根据多个条件搜索大型数组


                                            <p><p>我有一个 4K+ 项目的数组,使用 UISearchBar 和 UISearchController 对列表进行排序以进行匹配。我想通过几个标准来排序数组,但最重要的是用户首先输入的顺序</p>

<p>搜索 Controller 有 3 个范围按钮 </p>

<ul>
<li>类别</li>
<li>子类别</li>
<li>所有猫</li>
</ul>

<p>搜索数组中的项目是使用结构类来访问条件的:</p>

<pre><code>struct Item {
    var title: String
    var category: String
    var subCategory: String
    var allCat: String
}
</code></pre>

<p>标准的过滤方法是这样的:</p>

<pre><code>func filterContentForSearchText(_ searchText: String, scope: String = &#34;All&#34;) {

    self.filteredItems = allItems.filter({( item : Item) -&gt; Bool in

      let categoryMatch = (item.allCat == scope) || (item.category == scope)
      return categoryMatch &amp;&amp; item.title.lowercased().contains(searchText.lowercased())
      //return categoryMatch &amp;&amp; (item.title.lowercased().range(of:searchText.lowercased()) != nil)
    })

    tableView.reloadData()
}
</code></pre>

<p>这在项目很少的情况下很好,但如果我有很大的数组并且使用上面的 block 时,将包含大量不相关的项目,其中包含键入的字符串。</p>

<p>我可以通过 BEGINSWITH 使用谓词来获得更好的结果,但我无法满足类别的条件。我很确定下面的代码块无效,并希望获得更多经济建议。另一个障碍是数组包含多个单词的字符串。例如:</p>

<pre><code>array = [&#34;Apple&#34;, &#34;Apple Freshly Picked&#34;, &#34;Apple Green&#34;, &#34;Pear&#34;, &#34;Melon&#34;, &#34;Pear Yellow&#34;,....]
</code></pre>

<p>所以当用户开始输入“Ap”时的结果应该是</p>

<ul>
<li>苹果</li>
<li>苹果绿</li>
<li>新鲜采摘的苹果</li>
</ul>

<p>我在不满足搜索类别(结构)条件的情况下让它工作:</p>

<pre><code>func filterContentForSearchText(_ searchText: String, scope: String = &#34;All&#34;) {

    let words = searchText.components(separatedBy: &#34; &#34;)

    var word1 = &#34;&#34;
    var word2 = &#34;&#34;
    var word3 = &#34;&#34;

    var predicate = NSPredicate()
    var array = ()

    if scope == &#34;All&#34; {

      if words.count == 1{
            word1 = (words)
            predicate = NSPredicate(format: &#34;SELF BEGINSWITH %@ OR SELF LIKE %@&#34;, word1, word1)
      }
      else if words.count == 2{
            word1 = (words)
            word2 = (words)
            predicate = NSPredicate(format: &#34;SELF BEGINSWITH %@ AND SELF CONTAINS %@&#34;, word1, word2)
      }
      else if words.count == 3{
            word1 = (words)
            word2 = (words)
            word3 = (words)
            predicate = NSPredicate(format: &#34;SELF BEGINSWITH %@ AND SELF CONTAINS %@ AND SELF CONTAINS %@&#34;, word1, word2, word3)
      }

    } else {

      predicate = NSPredicate(format: &#34;title BEGINSWITH %@ AND category == %@&#34;, searchText, scope)

      if words.count == 1{
            word1 = (words)
            predicate = NSPredicate(format: &#34;SELF BEGINSWITH %@ OR SELF LIKE %@ AND category == %@&#34;, word1, word1, scope)
      }
      else if words.count == 2{
            word1 = (words)
            word2 = (words)
            predicate = NSPredicate(format: &#34;SELF BEGINSWITH %@ AND SELF CONTAINS %@ AND category == %@&#34;, word1, word2, scope)
      }
      else if words.count == 3{
            word1 = (words)
            word2 = (words)
            word3 = (words)
            predicate = NSPredicate(format: &#34;SELF BEGINSWITH %@ AND SELF CONTAINS %@ AND SELF CONTAINS %@ AND category == %@&#34;, word1, word2, word3, scope)
      }

    }

    array = (allItems as NSArray).filtered(using: predicate) as!
    self.filteredItems = array

    let lengthSort = NSSortDescriptor(key: &#34;length&#34;, ascending: true)
    let sortedArr = (self.filteredItems as NSArray).sortedArray(using: )
    self.filteredItems = sortedArr as!

    self.tableView.reloadData()
}
</code></pre>

<p>请问我该如何处理满足类别以及输入字符串匹配和字符串(第一个单词)的长度/范围的逻辑?</p>

<p>谢谢</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>我找到了路。我结合了 .filter 和 .sort 来得到结果:</p>

<pre><code>func filterContentForSearchText(_ searchText: String, scope: String = &#34;All&#34;) {

    let options = NSString.CompareOptions.caseInsensitive

    if scope == &#34;All&#34;{

      print(&#34;filtering All&#34;)
      self.filteredItems = allItems
            .filter{$0.title.range(of: searchText, options: options) != nil &amp;&amp; $0.allCat == scope}
            .sorted{ ($0.title.hasPrefix(searchText) ? 0 : 1) &lt; ($1.title.hasPrefix(searchText) ? 0 : 1) }
    }
    else{

      print(&#34;filtering \(scope)&#34;)
      self.filteredItems = allItems
            .filter{$0.title.range(of: searchText, options: options) != nil &amp;&amp; $0.category == scope}
            .sorted{ ($0.title.hasPrefix(searchText) ? 0 : 1) &lt; ($1.title.hasPrefix(searchText) ? 0 : 1) }

    }
    tableView.reloadData()
}
</code></pre>

<p>希望这对某人有所帮助</p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - Swift - 根据多个条件搜索大型数组,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/45521911/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/45521911/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - Swift - 根据多个条件搜索大型数组