【问题标题】:Swift: Evaluating if the letters in a String are contained within a longer StringSwift:评估字符串中的字母是否包含在更长的字符串中
【发布时间】:2022-11-17 01:53:37
【问题描述】:

好的,所以我当前的代码可以工作,但我感觉它的效率非常低。本质上,我需要评估一个 String 是否包含一个 String 的字母,该字母的长度是否与第一个字母相同或更短。 (想象一下,尝试使用单词 A 中存在的字母来拼写一个新单词单词 B。单词 B 可以比单词 A 短或相同的长度,但必须只使用单词 A 中的字母,并且不能使用相同的字母两次。 )

我目前的解决方案是将两个字符串排序到一个数组中,然后索引 Word B 数组中的每个字母,检查它是否出现在 Word A 数组中,然后从 Word A 数组中删除该字符。

let wordOne = "battle"
let wordTwo = "table"

var wordOneSorted = wordOne.sorted()
var wordTwoSorted = wordTwo.sorted()


for letter in wordTwoSorted {
  if wordOneSorted.contains(letter) {
    print("Valid Letter")
    let idx = wordOneSorted.firstIndex(of:letter)
    wordOneSorted.remove(at: idx!)
  } else {
    print("Invalid Letter")
  }
}

印刷: 有效信件 有效信件 有效信件 有效信件 有效信件

这行得通,但感觉很笨拙,我想看看我是否让一个简单的任务变得比我需要的更复杂。我只需要对整个比较进行评估,如果所有字母都比“True”有效,并且至少有一个无效而不是“False”。

谢谢!

【问题讨论】:

    标签: arrays swift comparison contains


    【解决方案1】:

    我想知道我会怎么做,这是另一种选择。对一个问题有不同的思考方式是件好事。

    我们创建一个[Character: (Int, Int)],其中键是字母,第一个元组值是 str1 中出现的次数,第二个元组值是 str2 中出现的次数。
    然后,我们检查 str1 中出现的所有值是否至少与 str2 中出现的次数相同。

    var counter: [Character: (Int, Int)] = [:]
    counter = str1.reduce(counter) {
        var values = $0
        var tuple: (Int, Int) = $0[$1, default: (0, 0)]
        values[$1] = (tuple.0 + 1, tuple.1)
        return values
    }
    counter = str2.reduce(counter) {
        var values = $0
        var tuple: (Int, Int) = $0[$1, default: (0, 0)]
        values[$1] = (tuple.0, tuple.1 + 1)
        return values
    }
    let doesInclude = counter.allSatisfy { _, tuple in
        tuple.0 >= tuple.1
    }
    print("(str1) includes all letters from (str2): (doesInclude)")
    

    "abc""cde" 的计数器值:

    ["d": (0, 1), "b": (1, 0), "c": (1, 1), "e": (0, 1), "a": (1, 0)]
    

    "battle""table" 的计数器值:

    ["t": (2, 1), "e": (1, 1), "a": (1, 1), "b": (1, 1), "l": (1, 1)]
    

    【讨论】:

      【解决方案2】:

      您的代码可以给出简单的好/坏响应,如下所示:

      let wordOne = "battle"
      let wordTwo = "table"
      
      var letters = wordOne
      var good = true
      for letter in wordTwo {
        if letters.contains(letter) {
          let idx = letters.firstIndex(of:letter)
          letters.remove(at: idx!)
        } else {
          good = false
          break
        }
      }
      print(good ? "Good" : "Bad")
      

      无需对每个单词的字母进行排序。这并没有使这种方法更有效。我添加 var letters 只是为了在循环运行时修改值。


      这是使用NSCountedSet 的替代方法。这不是一个纯粹的 Swift 类,而是由 Foundation 提供的。

      let wordOne = "battle"
      let wordTwo = "table"
      
      let set1 = NSCountedSet(array: Array(wordOne))
      let set2 = NSCountedSet(array: Array(wordTwo))
      let extra = set2.filter { set2.count(for: $0) > set1.count(for: $0) }
      print(extra.isEmpty ? "Good" : "Bad")
      

      NSCountedSetSet 的子类(实际上是 NSSetNSMutableSet 的子类),它为集合中的每个元素添加一个计数。

      filter 确保每个字母都足够。 extra 中剩余的任何内容都意味着 wordTwo 中的字母实例比 wordOne 中的字母更多。

      【讨论】:

        猜你喜欢
        • 2015-01-04
        • 2014-04-22
        • 1970-01-01
        • 2016-01-15
        • 2014-11-06
        • 2023-04-09
        • 2014-06-21
        • 1970-01-01
        相关资源
        最近更新 更多