【问题标题】:Filter array with prefix带前缀的过滤器数组
【发布时间】:2018-05-30 02:27:35
【问题描述】:

我有一个字符串类型的数组:

var Arr = ["apple", "banana", "orange", "grapes", "yellow banana", "urban"]

如何过滤数组中以我的关键字为前缀的每个单词? 现在我有了这个:

 .filter { $0.contains(keyword) }
 .sorted { ($0.hasPrefix(keyword) ? 0 : 1) < ($1.hasPrefix(keyword) ? 0 : 1) }

但如果我有关键字“ban”,它将返回“香蕉”、“黄色香蕉”和“城市”。 我只需要过滤数组元素中每个单词的前缀,就可以得到“香蕉”和“黄色香蕉”。

【问题讨论】:

  • 如果你只想过滤,为什么要调用sorted()?一个简单的.filter { $0.hasPrefix(keyword) } 怎么样?
  • @MartinR 谢谢,但这无济于事,就我而言,我认为我需要通过“”分隔符或其他方式拆分数组

标签: arrays swift filter


【解决方案1】:

您可以使用正则表达式来检查关键字是否 出现在单词边界(\b 模式):

let array = ["apple", "banana", "orange", "grapes", "yellow banana", "urban"]
let keyword = "ban"

let pattern = "\\b" + NSRegularExpression.escapedPattern(for: keyword)
let filtered = array.filter {
    $0.range(of: pattern, options: .regularExpression) != nil
}

print(filtered) // ["banana", "yellow banana"]

对于不区分大小写的搜索使用

options: [.regularExpression, .caseInsensitive]

改为。

【讨论】:

  • @DavidDavidoff:我仔细检查了上面带有let keyword = "yellow b" 的代码打印出["yellow banana"] 作为结果。你期待什么结果?
  • 是的,抱歉,是想将其发送到另一个评论。只有您的解决方案有效,也带有空格符号,我将您的答案标记为已接受。谢谢
【解决方案2】:

性能说明

我只是想参考过滤数组进行匹配引起的时间复杂度。

例如:

private var words: [String]

func words(matching prefix: String) -> [String]
{
   return words.filter { $0.hasPrefix(prefix) }
}

words(matching:) 将遍历字符串集合并返回 匹配前缀的字符串。

如果 words 数组中的元素数量很少,这是一个 合理的策略。但如果你处理的不止几个 一千个单词,遍历单词数组所需的时间将 不可接受words(matching:)的时间复杂度是O(k*n), 其中 k 是集合中最长的字符串,n 是 您需要检查的单词。

Trie 数据结构具有出色的性能特点 这类问题。

参考:https://www.raywenderlich.com/892-swift-algorithm-club-swift-trie-data-structure

【讨论】:

    【解决方案3】:

    您需要先使用 enumerateSubstrings 方法将字符串分解为单词,然后您可以检查是否有任何单词包含关键字前缀:

    extension String {
        var words: [String] {
            var words: [String] = []
            enumerateSubstrings(in: startIndex..<endIndex, options: .byWords) { word,_,_,_ in
                guard let word = word else { return }
                words.append(word)
            }
            return words
        }
    }
    

    let arr = ["apple", "banana", "orange", "grapes", "yellow banana", "urban"]
    let keyword = "ban"
    
    let filtered = arr.filter { $0.words.contains(where: {$0.hasPrefix(keyword)}) }
    
    filtered // ["banana", "yellow banana"]
    

    【讨论】:

      【解决方案4】:

      或者在 Swift 3+ 中:

      let array = ["apple", "banana", "orange", "grapes", "yellow banana", "urban"]
      let keyword = "ban"
      
      let filtered = array.filter {
          $0.components(separatedBy: " ").first { $0.hasPrefix(keyword) } != nil
      }
      print(filtered) // ["banana", "yellow banana"]
      

      【讨论】:

        【解决方案5】:

        您可以使用 hasPrefix 过滤数组,如下所示:

        // I Use two arrays, actualArray with original data and filteredArray contains data after filtration. You can use whatever is best for your scenario 
        
          filteredArray =  actaulArray.filter({ $0.hasPrefix(searchBar.text!)  })
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-12-11
          • 1970-01-01
          • 2021-06-23
          • 2020-11-28
          • 1970-01-01
          • 2013-05-03
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多