in_array()
関数を使用して確認します。 このようなアルゴリズムのパフォーマンスを改善する方法があります。
配列検索
通常、チェックは次のように行われます。
<?php $words = get_all_words_in_text($text); $badWords = ['$$$$', '@#$%', 'crud' /** ... */ ]; foreach ($words as $word) { if (in_array(strtolower($word), $badWords)) { echo 'Found bad word: ' . $word . "\n"; } }
この方法は問題を解決しますが、最も効果的ではありません。 メッセージ内の単語の配列を調べて、禁止されている関数
in_array()
リストにあるかどうかを確認します。 PHPでは、
in_array()
関数を
in_array()
するアルゴリズムは線形の複雑さ-O(n)を持ちます。 これは、悪い単語のリストが増えると、稼働時間が比例して長くなることを意味します。 もっと良いものを思いつくことができます。
ハッシュ検索
悪い単語のリストは事前にわかっているため、リスト内の禁止されている単語の数に依存しない一定の複雑さを持つように比較方法を修正できます。 これには連想配列を使用できます。 ハッシュテーブルの場合と同様に、配列内のキー検索速度はO(1)です。ただし、状況によっては発生しない場合もあります。
悪い単語の配列の構造を変更して、その値がキーになり、これらのキーの値がちょうど
true
になる場合、
isset()
関数を使用して、速度を大幅に向上させることができます。
<?php $words = get_all_words_in_text($text); $badWords = [ '$$$$' => true, '@#$%' => true, 'crud' => true // ... ]; foreach ($words as $word) { if (isset($badWords[strtolower($word)])) { echo 'Found bad word: ' . $word . "\n"; } }
性能試験
新しい方法をテストしてみましょう。 メソッドの同じデータセットに費やされた時間を示す簡単なテストを作成しました:「配列を検索」と「ハッシュで検索」。
<?php $total = 10000; $paragraph = 'this is a sentence. Crud! $$$$!'; $words = explode(' ', $paragraph); $badWordList = ['$$$$', '@#$%', 'crud', 'fud', 'fudd', 'dud']; $s = microtime(true); for ($j = 0; $j < $total; $j++) { foreach ($words as $word) { in_array(strtolower($word), $badWordList); } } echo "in_array: " . (microtime(true) - $s) . "\n"; $badWordHash = [ '$$$$' => true, '@#$%' => true, 'crud' => true, 'fud' => true, 'fudd' => true, 'dud' => true ]; $s = microtime(true); for ($j = 0; $j < $total; $j++) { foreach ($words as $word) { isset($badWordHash[strtolower($word)]); } } echo "hash: " . (microtime(true) - $s) . "\n";
リストからわかるように、テストでは10,000回の繰り返しが使用されます。 結果は次のとおりです。
in_array: 0.033491134643555 hash: 0.0069370269775391
ご覧のとおり、ハッシュ検索では、配列の検索に比べて480%の増加が見られました。
禁止されている単語の数が増えると、
in_array()
関数で配列を検索するのに必要な時間が長くなることを理解することが重要です。 ただし、
isset()
は要素の数に依存せず、その操作時間は一定のままです。 私が何を意味したかをお見せしましょう。 次の例では、禁止されている単語のリストは10,000個の要素で構成されます。
<?php $total = 10000; $paragraph = 'this is a sentence. Crud! $$$$!'; $words = explode(' ', $paragraph); // $sequence = []; for ($j = 0; $j < 10000; $j++) { $sequence[] = 'a' . $j; } $s = microtime(true); for ($j = 0; $j < $total; $j++) { foreach ($words as $word) { in_array(strtolower($word), $sequence); } } echo "in_array: " . (microtime(true) - $s) . "\n"; // $hash = array_fill_keys($sequence, true); $s = microtime(true); for ($j = 0; $j < $total; $j++) { foreach ($words as $word) { isset($hash[strtolower($word)]); } } echo "hash: " . (microtime(true) - $s) . "\n";
速度の違いはずっとよく見えます。 ハッシュ検索は、配列検索よりも3 162%高速です。
in_array: 20.464313983917 hash: 0.0064699649810791
一般的に、新しいものは何もありません
これは新しいアイデアではありません。 これは多くの言語でかなり一般的なアプローチです。 私は最近、「 プログラミングon Lua 」という本を読んでいるときに、そのようなタスクに常にハッシュ検索を使用していることに突然気付きました。
次回
in_array()
を使用してチェックするときは、連想配列のキーで
isset()
関数を代わりに使用した場合に作業が高速化されるかどうかを検討します。