Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/292.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
php将字符串匹配到多个关键字数组_Php_Regex_Arrays - Fatal编程技术网

php将字符串匹配到多个关键字数组

php将字符串匹配到多个关键字数组,php,regex,arrays,Php,Regex,Arrays,我正在编写一个基本的分类工具,它将获取一个标题,然后将其与一系列关键字进行比较。例如: $cat['dining'] = array('food','restaurant','brunch','meal','cand(y|ies)'); $cat['services'] = array('service','cleaners','framing','printing'); $string = 'Dinner at seafood restaurant'; 是否有创造性的方法循环浏览这些类别,或

我正在编写一个基本的分类工具,它将获取一个标题,然后将其与一系列关键字进行比较。例如:

$cat['dining'] = array('food','restaurant','brunch','meal','cand(y|ies)');
$cat['services'] = array('service','cleaners','framing','printing');
$string = 'Dinner at seafood restaurant';
是否有创造性的方法循环浏览这些类别,或查看哪个类别的匹配项最多?注意,在“dinning”数组中,我使用正则表达式来匹配单词candy的变体。我尝试了以下方法,但随着这些类别列表越来越长,我想知道这是否是最好的方法:

$keywordRegex = implode("|",$cat['dining']); 
preg_match_all("/(\b{$keywordRegex}\b)/i",$string,$matches]);
谢谢, 史蒂夫

编辑: 感谢@jmathai,我能够添加排名:

    $matches = array(); 
    foreach($keywords as $k => $v) {
        str_replace($v, '#####', $masterString,$count);
        if($count > 0){
            $matches[$k] = $count;
        }
    }
    arsort($matches);
$cat['dinning']=array('food'、'restaurant'、'bunch'、'mean');
$cat['services']=数组('service'、'cleaner'、'framing'、'printing');
$string=‘海鲜餐厅晚餐’;
$string=分解(“”,$string);
foreach($cat as$key=>$val){
$kwdMatches[$key]=计数(数组相交($string,$val));
}
阿索特(kwdMatches美元);
回声“;
印刷品(kwdMatches美元);
您正在执行O(n*m)查找,n是类别的大小,m是标题的大小。您可以尝试这样组织它们:

// One-time reverse category creation
$reverseCat = array();    
foreach ($cat as $cCategory => $cWordList) {
   foreach ($cWordList as $cWord) {
       if (!array_key_exists($cWord, $reverseCat)) {
           $reverseCat[$cWord] = array($cCategory);
       } else if (!in_array($cCategory, $reverseCat[$cWord])) {
           $reverseCat[$cWord][] = $cCategory;
       }
   }
}

// Processing a title
$stringWords = preg_split("/\b/", $string);

$matchingCategories = array();
foreach ($stringWords as $cWord) {
   if (array_key_exists($cWord, $reverseCat)) {
       $matchingCategories = array_merge($matchingCategories, $reverseCat[$cWord]);
   }
}

$matchingCategories = array_unique($matchingCategories);

然后,对于标题中的每个单词,检查
$categories[$word]
以查找类别-这会得到O(m)。

如果字数不是太多,那么创建反向查找表可能是一个好主意,然后对其运行标题

function rMatch ($a,$b) {
  if (preg_match('~^'.$b.'$~i',$a)) return 0;
  if ($a>$b) return 1;
  return -1;
}

$string = explode(' ',$string);
foreach ($cat as $key => $val) {
  $kwdMatches[$key] = count(array_uintersect($string,$val,'rMatch'));
}
arsort($kwdMatches);

echo "<pre>";
print_r($kwdMatches);

好的,这是我的新答案,它允许您在$cat[n]值中使用正则表达式…关于这段代码,我只知道一个我无法理解的警告…出于某种原因,如果在$cat[n]值的开头有任何类型的元字符或字符类,它就会失败

示例:
*食物
不起作用。但是
s.afood
sea.*
等。。。或者您的
cand(y | ies)
示例将起作用。我认为这对你来说已经足够了,因为我认为正则表达式的目的是处理不同的单词时态,在这种情况下,单词的开头很少改变

$cat['dining'] = array('food','restaurant','brunch','meal','candy','candies');
$cat['services'] = array('service','cleaners','framing','printing');
$string = 'Dinner at seafood restaurant';

$max = array(null, 0); // category, occurences
foreach($cat as $k => $v) {
  $replaced = str_replace($v, '##########', $string);
  preg_match_all('/##########/i', $replaced, $matches);
  if(count($matches[0]) > $max[1]) {
    $max[0] = $k;
    $max[1] = count($matches[0]);
  }
}

echo "Category {$max[0]} has the most ({$max[1]}) matches.\n";
函数rMatch($a,$b){
if(preg_match('~^'$b.$~i',$a))返回0;
如果($a>$b)返回1;
返回-1;
}
$string=分解(“”,$string);
foreach($cat as$key=>$val){
$kwdMatches[$key]=count(数组_uintersect($string,$val,'rMatch');
}
阿索特(kwdMatches美元);
回声“;
印刷品(kwdMatches美元);

这可以通过单个循环完成

为了提高效率,我会把糖果分成不同的条目。一个聪明的办法是用一些代币代替火柴。让我们用10


这不包括正则表达式?注意,如果需要排名,那么不是最后的
array_unique()
调用,而是在
$matchingCategories
上快速循环O(n)以构建计数表,然后是
arsort()
将给出降序排名。这是否处理了“cand(y)”呢‘条件?@daxiang28:对不起,我没有注意到,如果你只是把它写成‘糖果’,‘糖果’,那么它会的。你真的需要这里的regexp匹配吗?如果您可以在所有目标单词中使用任意regexp,那么我认为您必须将
$string
中的每个单词与
$cat
子数组中的每个单词进行匹配,速度非常慢。反向查找非常有趣。但在这种情况下,我必须处理这个词的每一个变体吗?如果我有一个关键字'piece',但字符串是'4块糖',它就不匹配了?@daxiang28:正确,你必须键入所有变体。不过,您可以绕过键入常规复数的需要。说出所有规则复数,只需在单词末尾加一个
+
,而不用再写一次。然后在
foreach($cWordList as$cWord)
中,剥离并检测末端的任何
+
,在检测到的地方,同时将
的“
变量添加到
$reverseCat
。然后你只需要输入不规则的复数和其他形式。我对php不太了解,但我怀疑散列比正则表达式更快。如果您将其中一个值作为实际正则表达式(如cand(y | ies)将其作为主题的正则表达式运行,例如,将正则表达式值放入一个单独的散列。纯粹是天才。我对其进行了一些简化,并在我编辑的帖子中添加了匹配计数。@Daxiang 28:不过,这种方法必须将字符串单独与
$cat
中的每个单词进行匹配,而不是在字符串和变体ab中对每个单词进行快速查找ove您只获得匹配单词数最多的第一个类别名称。(您的更改在这方面更好)。此外,仍然存在必须输入所有变体的问题。尽管这很聪明。我可能会尝试在preg_match_all调用中使用单词边界标记来消除str_replace步骤。但此问题更麻烦的方面是解决方案的运行时。随着每个类别数组中元素数量的增加,循环次数会增加0在searh术语中使用f字。在关联列表中旋转数组(考虑这里的集合)将以内存换取运行时。即使如此,我认为is方法存在扩展问题。不过,对于小型项目来说可能已经足够好了。
function rMatch ($a,$b) {
  if (preg_match('~^'.$b.'$~i',$a)) return 0;
  if ($a>$b) return 1;
  return -1;
}

$string = explode(' ',$string);
foreach ($cat as $key => $val) {
  $kwdMatches[$key] = count(array_uintersect($string,$val,'rMatch'));
}
arsort($kwdMatches);

echo "<pre>";
print_r($kwdMatches);
$cat['dining'] = array('food','restaurant','brunch','meal','candy','candies');
$cat['services'] = array('service','cleaners','framing','printing');
$string = 'Dinner at seafood restaurant';

$max = array(null, 0); // category, occurences
foreach($cat as $k => $v) {
  $replaced = str_replace($v, '##########', $string);
  preg_match_all('/##########/i', $replaced, $matches);
  if(count($matches[0]) > $max[1]) {
    $max[0] = $k;
    $max[1] = count($matches[0]);
  }
}

echo "Category {$max[0]} has the most ({$max[1]}) matches.\n";