我对这种情况感到困惑。我有一个包含300个或更多单词的数组列表,还有另一个包含500个或更多单词的句子列表。所以现在我要提取与单词列表匹配的句子。例如,
$a = ['lorem', 'ipsum', 'one', 'three', 'five'];
$b = [
'lorem ipsum dolor',
'one word',
'three horse',
'ten dolor'
];
我想基于$ a个单词提取$ b个句子。我不想使用foreach,因为它将是n个循环。解决这个问题的可行方法是什么?
答案 0 :(得分:1)
通过调用preg_grep
和正则表达式的神奇之处。
$a = ['lorem', 'ipsum', 'one', 'three', 'five'];
$pattern = '/\b('.implode('|',array_map(function($w){
return preg_quote($w,'/'); //escape the delimiter too
},$a)).')\b/i';
$b = [
'lorem ipsum dolor',
'one word',
'three horse',
'ten dolor'
];
print_r(preg_grep($pattern, $b));
输出:
Array
(
[0] => lorem ipsum dolor
[1] => one word
[2] => three horse
)
如果您确定“单词”将不包含正则表达式的任何特殊内容(主要是标点符号),则可以这样简单地完成操作:
function matchWordsInSentances($words, array $sentances){
if(!is_array($words))$words = [$words];
return preg_grep('/\b('.implode('|',$words).')\b/i', $sentances);
}
preg_grep -返回与模式匹配的数组条目
数组 preg_grep (字符串 $ pattern ,数组 $ input [,int $ flags = 0]))
返回由与给定模式匹配的输入数组元素组成的数组。
http://php.net/manual/en/function.preg-grep.php
为了您的方便起见,数组图+ preg报价是一项安全功能:
preg_quote -引用正则表达式字符 字符串 preg_quote (字符串 $ str [,字符串 $ delimiter = NULL])
preg_quote()采用str并将反斜杠放在正则表达式语法中每个字符的前面。如果您有一个需要在某些文本中匹配的运行时字符串,并且该字符串可能包含特殊的正则表达式字符,这将很有用。
特殊的正则表达式字符为:。 \ + *吗? [^] $(){} =! <> | :-
请注意, / 不是特殊的正则表达式字符。
定界符如果指定了可选定界符,也将对其进行转义。这对于转义PCRE功能所需的分隔符很有用。 / 是最常用的定界符。
http://php.net/manual/en/function.preg-quote.php
您没有“必须”使用它们,它们确实在“单词”数组上添加了迭代,但是如果您可以使用.
或?
甚至是{{1 }},您可能想使用它。基本上,它逃避了那些事情,因此它们不会被解释为正则表达式的一部分。如果您了解Regex,您可以随时忽略它,并像*
这样利用$words = ["shoes?"]
和shoe
匹配它。
正则表达式说明
所使用的模式非常向前:
shoes
单词边界,空格,标点,字符串的开头和结尾\b
捕获组(...)
或(|
或word
等)word
不区分大小写的标志。在这种情况下,完整模式如下:
\i
或者用英语,从单词边界开始,匹配列表中的任何单词,结束于单词边界,不区分大小写地匹配
。明智的表现,谁知道?如有疑问,请对它们进行基准测试并比较时间差。 /\b(lorem|ipsum|one|three|five)\b/i
的好处是我们正在折叠其中一个数组,然后让PHP和PCRE(Regex引擎)处理实现所需的循环。
享受。