If-Statement in' Array#each'返回' true'仅限于最后一个元素

时间:2017-10-03 22:36:16

标签: ruby

我正在为我的discord服务器编写机器人,我想充当亵渎过滤器。我从文本文件中读取了一个坏词列表,并将它们存储在一个数组中。每当用户发送消息时(在机器人正在监听的频道中),机器人然后检查该消息是否包括这些坏词中的一个或多个。为此,我使用以下代码:

badWords.each { |badword|
  if content.downcase.include? badword
    ...
  end
}

我的问题是,只有当消息内容中的坏词与数组中的最后一个字匹配时,if语句才会返回true。如果它匹配数组的任何其他元素,则返回false

我是否误解了Array#each的任何功能?

2 个答案:

答案 0 :(得分:2)

尝试strip一个坏词,因为它最终可以有\n个签名。

if content.downcase.include?(badword.strip)

答案 1 :(得分:1)

我会将您的代码分解为更小的部分,以便您可以更好地了解正在发生的事情,然后使用Ruby的Enumerable methods之一来帮助使事情更简洁。另外,让我们使用Ruby_case的Ruby约定(bad_words而不是badWords)。

首先,让我们确保您的bad_words数组不包含任何不需要的字符。最好一次修改bad_words集合,而不是每次都修改每个元素。

虽然我们正在使用它,但由于我们的集合不会包含重复项,并且由于我们将多次搜索匹配元素,因此我们可以通过将数组转换为集合来大大提高效率:

require 'set'
bad_words = bad_words.map(&:strip).to_set

接下来让我们编写一个方法来检查内容是否包含坏词。我们将在方法名称的末尾加上一个问号,表示它返回一个布尔值:

def profane?(content)
  bad_words.any? { |bad_word| content.include?(bad_word) }
end

如果传入下一个块的任何项返回#any?,则true方法返回true。

现在,您的操作代码可以致电profane?并采取相应措施:

def filter_bad_words(content)
  if profane?(content)
    bot.send_message(event.channel.id, "Sorry #{event.user.name}, this message made my profanity senses tingle!")
    bot.send_message(344559522003812354, "PROFANITY WARNING!!\n user: #{event.user.name}\n message: #{event.content}\n Please check if it is a cause for a warning. Use !?warn to give the user a warning.")
    event.message.delete
    true
  end
end

如果内容是亵渎的话,我已经让方法返回true,如果内容不是亵渎的话,我会默认返回nil。如果您愿意,可以使用不同的返回值,并且可以根据该响应采取进一步的操作。