假设我有一个我要扫描的传入字符串,看它是否包含我选择的任何“糟糕”字样。 :)
将字符串拆分成数组更快,并将坏字保留在数组中,然后遍历每个坏字以及每个传入的字,看看是否有匹配,有点像: / p>
badwords.each do |badword|
incoming.each do |word|
trigger = true if badword == word
end
end
或者执行此操作会更快:
incoming.each do |word|
trigger = true if badwords.include? word
end
或者保留字符串的速度更快,并运行带有正则表达式的正则表达式的.match():
/\bbadword1\b|\bbadword2\b|\bbadword3\b/
或者性能差异几乎完全可以忽略不计?一直想知道这件事。
答案 0 :(得分:5)
通过在找到匹配时不停止循环,您正在为正则表达式提供优势。尝试:
incoming.find{|word| badwords.include? word}
我的钱仍然在正则表达式,但应该简化为:
/\b(badword1|badword2|badword3)\b/
或使其公平对抗:
/\a(badword1|badword2|badword3)\z/
答案 1 :(得分:3)
一旦编译完成,正则表达式是实时最快的(即真正长的传入字符串,许多类似的坏字等),因为它可以在incoming
in situ上运行并处理重叠部分你的"坏词"真的很好。
答案 2 :(得分:2)
答案可能取决于要检查的坏词的数量:如果只有一个坏词,它可能不会产生巨大的差异,如果有50个那么检查一个数组可能会变慢。另一方面,有数十或数十万个单词,正则表达式可能也不会太快
如果您需要处理大量不良单词,您可能需要考虑拆分成单个单词,然后使用bloomfilter来测试单词是否可能是坏的。
答案 3 :(得分:2)
这并没有激动地回答你的问题,但这肯定有助于解决它。
举一些例子来说明你需要做些什么,然后把它们放到基准分数上。
您可以在ruby here
中找到如何进行基准测试只需将varoius表单放在报告块之间并获得基准,并自行决定最适合您的方式。
http://ruby.about.com/od/tasks/f/benchmark.htm
http://ruby-doc.org/stdlib-1.9.3/libdoc/benchmark/rdoc/Benchmark.html
为了获得更好的解决方案,请使用真实数据进行测试。
基准总是优于讨论:)
答案 4 :(得分:1)
如果要扫描字符串是否出现单词,请使用scan
查找字符串。
使用Regexp.union
构建一个模式,找到黑名单中的字符串。您将希望用\b
包装结果以强制匹配单词边界,并使用不区分大小写的搜索。
让您了解Regexp.union
如何提供帮助:
words = %w[foo bar]
Regexp.union(words)
=> /foo|bar/
'Daniel Foo killed him a bar'.scan(/\b#{Regexp.union(words)}\b/i)
=> ["foo", "bar"]
如果您想要更多控制,您还可以使用Regexp.new
或/.../
来构建模式:
Regexp.new('\b(?:' + words.join('|') + ')\b', Regexp::IGNORECASE)
=> /\b(?:foo|bar)\b/i
/\b(?:#{words.join('|')})\b/i
=> /\b(?:foo|bar)\b/i
'Daniel Foo killed him a bar'.scan(/\b(?:#{words.join('|')})\b/i)
=> ["Foo", "bar"]
作为一个建议,你发现冒犯的黑名单词很容易被用户欺骗,而且往往会给出错误的结果,因为许多“冒犯性”词语在某些情境下只会令人反感。用户可以故意拼错它们或使用“l33t”发言并且几乎取之不尽的替代拼写可以让你不断更新你的列表。这是一些人欺骗系统的乐趣来源。
我曾经被赋予了类似的任务并且写了一名翻译来为“冒犯性”单词提供替代拼写。我从一个我从互联网上收集的单词和术语列表开始,开始运行我的代码。在数百万的替代品被添加到数据库之后,我拔掉了插头并向管理层表明这是一个愚蠢的事,因为愚弄它是微不足道的。