php preg_match_all()每个单词70次| Api端点|性能

php preg_match_all()每个单词70次| Api端点|性能,php,regex,performance,Php,Regex,Performance,我有一张70个单词的单子。此列表用于检查用户输入。用户输入的是文本,平均有30-100个单词。如果“我的列表”中的一个单词在文本中,则用户文本将被删除,否则是允许的。在大多数情况下,它是被允许的,因此它将在所有单词中循环 要检查单词是否在我使用的用户文本中,请执行以下操作: $susWords = SuspiciousWord::where('checked', true)->get(); $foundSusWord = false; foreach ($susWords as $wor

我有一张70个单词的单子。此列表用于检查用户输入。用户输入的是文本,平均有30-100个单词。如果“我的列表”中的一个单词在文本中,则用户文本将被删除,否则是允许的。在大多数情况下,它是被允许的,因此它将在所有单词中循环

要检查单词是否在我使用的用户文本中,请执行以下操作:

$susWords = SuspiciousWord::where('checked', true)->get();

$foundSusWord = false;
foreach ($susWords as $word) {
    if (preg_match_all("/" . $word->word . "/i", $user->flirttext)) {
        $foundSusWord = true;     
    break;
    }
} 
说到正则表达式和性能,我不是专家。性能可能是一个问题吗?

您可以使用
strpos()

比正则表达式更有效

以下是一些基准:

  • 使用
    stripos($user->text,$word->word)!=false
    以加快检查速度,因为不需要正则表达式
  • 使用
    preg_match('/\b('.intlode('.|',array_column($susWords,'word')))。)\b/,$user->text)
    一次检查所有单词

  • 编辑:正如@Justinas所指出的,如果文本中只有标点符号,这种方法就不是很好。在这种情况下根本不应该使用。留下它作为参考

    还可以使用数组_intersect来避免循环:

    $wordlist = explode(' ', $user->flirttext));
    if (count(array_intersect($susWords, $wordlist)) > 0) {
        // found a bad word, do something
    }
    

    请参阅为什么使用正则表达式而不是
    stripos()!=false
    ?如果您搜索
    hello
    并且用户输入了
    foo bar hello.?
    ?您是对的,事实上,它需要更多的解析,可能会丢失一些其他字符,因此不是一个真正好的方法。我将把答案留给其他人看,不要犯同样的错误,而是编辑以警告人们哪一个更快?我的两个单词是模式,下面是一个示例\sig\s。我可以对所有非模式字使用第一种方法,对模式使用正则表达式方法。@Roman
    \sig\s
    包含
    \big\b
    。正则表达式总是比简单的字符串运算慢是的,我理解,但是我应该用你的第二个例子来表示所有的单词,还是我应该把它分成两个函数。值得吗?我只有2个带模式的单词。第二个示例有错误,如果它是字符串的一部分,它将找不到该单词,例如,如果用户输入的是
    sex
    ,则将找不到单词
    sex
    ,这很糟糕,我原来的正则表达式已经找到了它。既然您是通过
    加入的,那么创建两个列表就没有意义了