任何更快,更简单的替代php preg_match

时间:2010-11-30 13:56:36

标签: php regex cakephp preg-match

我正在使用cakephp 1.3,我有textarea用户提交文章。在提交时,我想查看文章中的某些关键词,并在文章中添加相应的标签。

我在考虑preg_match,但preg_match模式必须是字符串。所以我必须循环一个数组(大)。

是否有更简单的方法来插入模式的关键字数组。

感谢您的帮助。

感谢。

6 个答案:

答案 0 :(得分:3)

我建议将关键字数组视为哈希表。小写文章文本,按空格分解,然后循环遍历爆炸数组的每个单词。如果哈希表中存在该单词,则将其推送到新数组,同时跟踪其被查看的次数。

在这种情况下,我运行了一个快速基准测试,将正则表达式与哈希表进行比较。要使用正则表达式运行1000次,需要17秒。要使用哈希表运行1000次,需要0.4秒。它应该是一个O(n + m)过程。

$keywords = array("computer", "dog", "sandwich");
$article = "This is a test using your computer when your dog is being a dog";
$arr = explode(" ", strtolower($article));
$tracker = array();

foreach($arr as $word){
    if(in_array($word, $keywords)){
        if(isset($tracker[$word]))
            $tracker[$word]++;
        else 
            $tracker[$word] = 1;
    }
}

$ tracker数组将输出:“computer”=> 1,“dog”=> 2.然后,您可以执行该过程以确定要使用的标记。或者,如果您不关心关键字出现的次数,您可以跳过跟踪器部分,并在关键字出现时添加标签。

编辑:关键字数组可能需要是反向索引数组,以确保最快的查找。我不确定in_array()是如何工作的,但是如果它搜索的话,那就没那么快了。反向索引数组看起来像

array("computer" => 1, "dog" => 1, "sandwich" => 1); // "1" can be any value

然后你会做isset($ keywords [$ word])检查单词是否与关键字匹配,而不是in_array(),它应该给你O(1)。其他人可能会为我澄清这一点。

答案 1 :(得分:2)

当然,您可以尝试使用一个正则表达式匹配所有关键字,例如/word1|word2|word3/,但我不确定它是您正在寻找的。而且我认为这将是非常沉重和耗费资源的。

相反,您可以尝试使用其他方法,例如将文本拆分为单词并检查单词是否有趣。我会使用str_word_count()使用像:

这样的东西
$text = 'this is my string containing some words, some of the words in this string are duplicated, some others are not.';
$words_freq = array_count_values(str_word_count($text, 1));

将文本拆分为单词并计算出现次数。然后,您可以查看in_array($keyword, $words_freq)array_intersect(array_keys($words_freq), $my_keywords)

如果您对关键字案例不感兴趣,可以在继续分词之前strtolower()整个文字。

当然,确定哪种方法最好的唯一方法是设置一些测试,通过针对某些“代表性”和相当长的文本运行各种搜索功能并测量执行时间和资源使用情况(尝试{{1} }和microtime(TRUE)对此进行基准测试。)

编辑:我清理了一些代码并添加了一个缺少的分号:)

答案 2 :(得分:2)

如果要从数组中查找多个单词,请将所述数组合并为正则表达式:

 $regex_array = implode("|", array_map("preg_escape", $array));
 preg_match_all("/($regex_array)/", $src, $tags);

这会将您的数组转换为/(word|word|word|word|word|...)/。 arrray_map和preg_escape部分是可选的,仅在$ array 可能包含特殊字符时才需要。

在这种情况下避免使用strpos和循环。 preg_match可以更快地搜索替代品。

答案 3 :(得分:1)

如果您不需要正则表达式的强大功能,则应使用strpos()

您仍然需要遍历单词数组,但strpospreg_match快得多。

答案 4 :(得分:0)

strtr()

  

如果给出两个参数,则第二个   应该是表单中的数组   array('from'=>'到',...)。回报   value是一个所有的字符串   数组键的出现有   被相应的替换   值。将尝试最长的密钥   第一。一旦子串已经存在   换了,它的新价值不会   再次搜索。

答案 5 :(得分:0)

手动添加标签?就像我们在SO处添加标签一样。