PHP匹配字符串到多个关键字数组
我正在写一个基本的分类工具,将采取一个标题,然后将其与一个关键字数组进行比较。例如:PHP匹配字符串到多个关键字数组
$cat['dining'] = array('food','restaurant','brunch','meal','cand(y|ies)');
$cat['services'] = array('service','cleaners','framing','printing');
$string = 'Dinner at seafood restaurant';
是否有创造性的方法来循环这些类别或查看哪些类别具有最匹配的?请注意,在“餐饮”数组中,我使用正则表达式来匹配单词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);
这可以通过一个循环完成。
我会将糖果和糖果分成单独的条目以提高效率。一个聪明的窍门是用一些标记替换匹配。我们用10#。
$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";
$cat['dining'] = array('food','restaurant','brunch','meal');
$cat['services'] = array('service','cleaners','framing','printing');
$string = 'Dinner at seafood restaurant';
$string = explode(' ',$string);
foreach ($cat as $key => $val) {
$kwdMatches[$key] = count(array_intersect($string,$val));
}
arsort($kwdMatches);
echo "<pre>";
print_r($kwdMatches);
这不包含正则表达式? – 2011-02-05 01:05:14
嗯...这不包括通配符/变体匹配... – 2011-02-05 01:07:49
你n个执行O(N * M)查找是您的类别的大小和M为标题的大小。你可以试试他们组织这样的:
const $DINING = 0;
const $SERVICES = 1;
$categories = array(
"food" => $DINING,
"restaurant" => $DINING,
"service" => $SERVICES,
);
然后在标题的每个字,检查$categories[$word]
找到类别 - 这让你O(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);
请注意,如果需要排名,那么不要在末尾使用`array_unique()`调用,而是使用`$ matchingCategories`来构建一个计数表,然后是一个`arsort()`将给出下降的排名。 – Orbling 2011-02-05 01:20:42
好这里是我的新的答案,让您在$猫[N]值......只有一个关于这个代码,我想不通......出于某种原因需要注意的,它失败使用正则表达式如果您在$ cat [n]值的开头有任何类型的元字符或字符类。
例如:.*food
不起作用。但是s.afood
或sea.*
等...或者您的cand(y|ies)
的示例将工作。我认为这对你来说足够好,因为我认为正则表达式的意义在于处理不同时态的单词,并且在这种情况下单词的开头几乎不会改变。
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);
不知道PHP太好,但我怀疑哈希会比正则表达式更快。如果你有一个值作为一个实际的正则表达式(如cand(y | ies))作为正则表达式运行它,例如把正则表达式值放入一个单独的散列表中。 – sln 2011-02-05 02:04:46