从一个数组中删除另一个数组中存在的元素。

12

有一个单词列表和一个禁止使用的单词列表。我想遍历单词列表,并删除所有被禁用的单词。这就是我最终做的(请注意catched布尔值):

puts "Give input text:"
text = gets.chomp
puts "Give redacted word:"
redacted = gets.chomp

words = text.split(" ")
redacted = redacted.split(" ")
catched = false

words.each do |word|
  redacted.each do |redacted_word|
    if word == redacted_word
        catched = true
        print "REDACTED "
        break
    end
  end
    if catched == true
        catched = false
    else
        print word + " "
    end
end

有没有合适/有效的方法?

3个回答

20

它也可以工作。

words - redacted

+, -, &这些方法非常简单实用。

irb(main):016:0> words = ["a", "b", "a", "c"]
=> ["a", "b", "a", "c"]
irb(main):017:0> redacted = ["a", "b"]
=> ["a", "b"]
irb(main):018:0> words - redacted
=> ["c"]
irb(main):019:0> words + redacted
=> ["a", "b", "a", "c", "a", "b"]
irb(main):020:0> words & redacted
=> ["a", "b"]

唯一的问题是这不太灵活。例如,如果您需要使其不区分大小写,则必须切换到其他解决方案。 - Mark Thomas

16
你可以使用.reject来排除redacted数组中出现的所有禁用词:
words.reject {|w| redacted.include? w}

演示

如果您想获取在words数组中存在的被禁止单词列表,可以使用.select

words.select {|w| redacted.include? w}

演示


顺便说一句,离题了。无论如何只删除第一个出现的? - mirageglobe

1
这可能更加“优雅”。它是否比你的解决方案更有效,我不知道。
puts "Give input text:"
original_text = gets.chomp
puts "Give redacted word:"
redacted = gets.chomp

redacted_words = redacted.split

print(
  redacted_words.inject(original_text) do |text, redacted_word|
    text.gsub(/\b#{redacted_word}\b/, 'REDACTED')
  end
)

这里发生了什么事情?
  • 我使用String#split而没有参数,因为' '是默认值
  • 使用Array#inject,下面的块(从do开始到end结束)将针对数组中的每个元素执行——在这种情况下,我们的禁止单词列表。
    • 在每一轮中,块的第二个参数将是数组中相应的元素
    • 块的第一个参数将是上一轮块的返回值。对于第一轮,将使用inject函数的参数(在我们的例子中为original_text)。
    • 最后一轮块的返回值将用作inject函数的返回值。
  • 在块中,我替换了文本中当前处理的被编辑单词的所有出现。
    • String#gsub执行全局替换
    • 作为要替换的模式,我使用正则表达式字面量(/.../)。除此之外,它不是一个字面量,因为我正在对它执行字符串替换(#{...}),将当前处理的被编辑单词放入其中。
    • 在正则表达式中,我用\b单词边界匹配器将要编辑的单词括起来。它们匹配字母数字字符和非字母数字字符(或者反过来)之间的边界,而不匹配任何字符本身。如果一个字符串以字母数字字符开头或结尾,\b也会分别匹配字符串的开头或结尾,这样我们就可以用它来匹配整个单词。
  • inject的结果(即块的最后一次执行的结果,即在所有替换发生时的文本)被传递为print的参数,它将输出现在被编辑的文本。

注意,除了您的解决方案之外,我的解决方案将不会将标点符号视为相邻单词的一部分。

此外,请注意,我的解决方案将容易受到正则表达式注入攻击。

示例1:

Give input text:
A fnord is a fnord.
Give redacted word:
ford fnord foo

我的输出:

A REDACTED is a REDACTED.

您的输出:
A REDACTED is a fnord.

示例2:
Give input text:
A fnord is a fnord.
Give redacted word:
fnord.

我的输出:

A REDACTEDis a fnord.

(注意如何解释 . 以匹配任何字符。)
您的输出:
A fnord is a REDACTED.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接