在 PHP 中,将字符串与关键字列表匹配的最有效方法是什么


In PHP, what is the most efficient way to match a string against a list of keywords?

我有一个关键字列表,需要检查字符串中是否有任何关键字。 例如:

/* Keywords */
Rock
Paper
Scissors
/* Strings */
"This town rocks!"    /* Match */
"Paper is patient"    /* Match */
"Hello, world!"       /* No match */

我可以将我的关键字放在一个数组中,遍历它并在每次迭代时执行 preg_match() 或 substr(),但这似乎有点 cpu 昂贵。我已经用正则表达式搞砸了一点,但没有取得多大成功。

最有效的

方法是什么(就精简代码和低 CPU 负载而言)来做到这一点?

请注意,比较必须不区分大小写。

具有所有替代方案的正则表达式将确保字符串被扫描一次,而不是 N 次扫描 N 个关键字。PCRE 库得到了很好的优化。

preg_match('/rock|paper|scissors/i', $string);

如果您的关键字具有共同的前缀并且您利用它(主要是通过构建 trie 并内联它),它会变得更快:

preg_match('/rock|paper|sci(?:ssors|ence)/i', $string);

最后是

preg_grep($regex, $array_of_strings);

这将与字符串数组匹配并返回匹配的字符串。

只是为了查看是否找到任何关键字,您可以将关键字作为数组来执行此操作:

if(str_ireplace($keyword_array, '', $string) != $string) {
    //match
} else {
    //no match
}

如果你事先不知道你的关键词,并且你有多个字符串想要搜索,你可以把你的关键词内爆到正则表达式中,并对字符串进行 grep:

$keywords = array ('Rock', 'Paper', 'sciSSors');
$strings  = array (
    "This town rocks!",
    "Hello, world!",
    "Paper is patient",
);
$rc = preg_grep(
    sprintf('/%s/i', implode('|', array_map('preg_quote', $keywords))),
    $strings
);
/**
array(2) {
  [0]=>
  string(16) "This town rocks!"
  [2]=>
  string(16) "Paper is patient"
}
*/

在这里看到它。