4

スキャンして、「悪い」と選択した単語が含まれているかどうかを確認したい着信文字列があるとします。:)

文字列を配列に分割し、悪い単語を配列に保持してから、各悪い単語と各着信単語を反復処理して、次のような一致があるかどうかを確認する方が高速ですか?

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/

それとも、パフォーマンスの違いはほとんど無視できるものですか? これはしばらくの間疑問に思っていました。

4

5 に答える 5

5

一致するものが見つかったときにループを停止しないことで、正規表現に利点をもたらします。試す:

incoming.find{|word| badwords.include? word}

私のお金はまだ正規表現にありますが、これは次のように簡略化する必要があります。

/\b(badword1|badword2|badword3)\b/

またはそれを公正な戦いにするために:

/\a(badword1|badword2|badword3)\z/
于 2012-09-02T08:33:54.000 に答える
3

incoming コンパイルされると、Regex はその場で実行でき、「悪い言葉」の重複部分を非常にうまく処理できるため、実際のライブ (つまり、非常に長い受信文字列、多くの類似の悪い言葉など) で最速です。

于 2012-09-02T07:10:48.217 に答える
2

答えはおそらく、チェックする悪い単語の数に依存します。悪い単語が 1 つしかない場合は、おそらく大きな違いはありません。50 個ある場合、配列のチェックはおそらく遅くなります。一方、数万または数十万の単語では、正規表現もおそらく速すぎません。

大量の不適切な単語を処理する必要がある場合は、個々の単語に分割してから、ブルームフィルターを使用してその単語が不適切であるかどうかをテストすることを検討してください。

于 2012-09-02T08:50:56.590 に答える
2

これはあなたの質問に正確に答えるものではありませんが、これは間違いなく解決に役立ちます.

あなたが達成しようとしていることをいくつか例を挙げて、それらをベンチマークに入れます。

Ruby でベンチマークを実行する方法については、こちらを参照してください。

レポートブロックの間にさまざまなフォームを配置し、ベンチマークを取得して、自分に最適なものを自分で決定してください。

http://ruby.about.com/od/tasks/f/benchmark.htm

http://ruby-doc.org/stdlib-1.9.3/libdoc/benchmark/rdoc/Benchmark.html

より良いソリューションを得るには、実際のデータを使用してテストしてください。

ベンチマークは常に議論よりも優れています:)

于 2012-09-02T09:40:36.587 に答える
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」スピーチを使用したりして、リストを絶えず更新する代替スペルをほぼ無尽蔵に提供することができます。システムをだますことは、一部の人々にとって楽しみの源です。

私はかつて同様の仕事を与えられ、「不快な」単語の代替スペルを提供する翻訳者を書きました。インターネットから収集した単語と用語のリストから始めて、コードの実行を開始しました。数百万の代替がデータベースに追加された後、私はプラグを抜いて、それをだますのは簡単だったので、それがばか者の用事であることを管理に示しました。

于 2012-09-03T06:10:25.913 に答える