搜索包含字符串的PHP数组元素

49
$example = array('An example','Another example','Last example');

如何对上述数组进行松散搜索单词"Last"?

echo array_search('Last example',$example);

上面的代码只会在针对value的完全匹配时回显该值的key,这不是我想要的结果。我需要像这样的东西:

echo array_search('Last',$example);

如果值包含单词“Last”,我想要输出该值的键。


4
遍历数组,使用您喜欢的字符串比较方法,记住键(key)... - deceze
7个回答

71

要查找与搜索条件匹配的值,你可以使用 array_filter 函数:

$example = array('An example','Another example','Last example');
$searchword = 'last';
$matches = array_filter($example, function($var) use ($searchword) { return preg_match("/\b$searchword\b/i", $var); });

现在$matches数组将仅包含原始数组中包含单词last(不区分大小写)的元素。

如果您需要找到符合条件的值的键,则需要循环遍历该数组:

$example = array('An example','Another example','One Example','Last example');
$searchword = 'last';
$matches = array();
foreach($example as $k=>$v) {
    if(preg_match("/\b$searchword\b/i", $v)) {
        $matches[$k] = $v;
    }
}

现在数组$matches包含原始数组中值包含(不区分大小写的)单词last的键值对。


实际上,这会导致语法错误,未知的位置,并且不起作用...当我像这样评论它时$matches = array_filter($example, function($var) use ($searchword) { return preg_match("/\b$searchword\b/i", $var); });脚本继续工作,但是当我添加它时,它就会崩溃。 - Lachezar Raychev
@LachezarRaychev 你使用的是哪个版本的php?它可以在5.4、5.5和5.6中运行。 - Aleks G
2
这里没有技术上的错误,但我真的不明白为什么要在这里使用正则表达式,strpos() 不是同样适用且更快吗? - But those new buttons though..
@billynoah 是的,它会 :) - Aleks G
不要忘记对输入字符串使用 preg_quote() 函数进行转义,否则如果您的输入字符串包含正则表达式中具有特殊意义的字符,则会产生不可预测的结果:return preg_match("/\b".preg_quote($searchword)."\b/i", $var); - Bud Damyanov
显示剩余5条评论

24
function customSearch($keyword, $arrayToSearch){
    foreach($arrayToSearch as $key => $arrayItem){
        if( stristr( $arrayItem, $keyword ) ){
            return $key;
        }
    }
}

2
@MarcioSimao 这将只返回第一个匹配元素的键,而不是所有匹配项的键数组。 - Aleks G
@AleksG,这正是我在寻找的。如果我没记错,问题就是关于同样的事情。最后一个用户的话是:“如果值包含单词“Last”,我想要值的键回显”。 - Marcio Mazzucato
@MarcioSimao 可能这对你解决问题有帮助,但它仅限于单个匹配。如果你有多个包含单词“_last_”的值,那么你只能找到第一个符合条件的代码。 - Aleks G
@AleksG,感谢您的建议!但在我的情况下,我需要找到第一个键,因此这段代码更加优化和易读。 - Marcio Mazzucato
PHP 手册指出,不应使用 strstr()stristr() 来检查子字符串的存在,因为这样会影响效率。 - mickmackusa

14
$input= array('An example','Another example','Last example');
$needle = 'Last';
$ret = array_keys(array_filter($input, function($var) use ($needle){
    return strpos($var, $needle) !== false;
}));
这将给你所有值包含 "needle" 的键。

3

它会找到第一个匹配的元素的键:

echo key(preg_grep('/\b$searchword\b/i', $example));

如果需要所有的键,请使用 foreach:

foreach (preg_grep('/\b$searchword\b/i', $example) as $key => $value) {
  echo $key;
}

甚至可以使用array_keys(preg_grep('/\b$searchword\b/i', $example))。我也需要相同的功能,本来打算编写一个包装函数,但这个完美无缺。 - MSpreij
当将变量添加到模式中时,我们应该查看 preg_quote() - mickmackusa

0

我不喜欢正则表达式,因为据我所知,它们总是比普通字符串函数慢。所以我的解决方案是:

function substr_in_array($needle, array $haystack)
{
    foreach($haystack as $value)
    {
        if(strpos($value, $needle) !== FALSE) return TRUE;
    }
    return FALSE;
}

这并不像预期的那样返回关键字(在其他地方已经展示过)。 - mickmackusa

0

Aleks G给出的答案不够准确。

$example = array('An example','Another example','One Example','Last example');
$searchword = 'last';
$matches = array();
foreach($example as $k=>$v) {
    if(preg_match("/\b$searchword\b/i", $v)) {
        $matches[$k] = $v;
    }
}

这行代码

if(preg_match("/\b$searchword\b/i", $v)) {

应该被这些替换

$match_result = preg_match("/\b$searchword\b/i", $v);
if( $match_result!== false && $match_result === 1 ) {

或者更简单地说

if( preg_match("/\b$searchword\b/i", $v) === 1 ) {

根据http://php.net/manual/en/function.preg-match.php的规定

如果模式匹配给定的主题,则preg_match()返回1,如果不匹配则返回0,如果发生错误则返回FALSE。


在将变量添加到模式中时,我们应该使用 preg_quote()。在循环中使用 preg_match() 作为过滤器更优雅的表达方式是使用 preg_grep() - mickmackusa

-1

我也在寻找解决 OP 问题的方法,通过谷歌搜索我偶然发现了这个问题。然而,这些答案都不能满足我的需求,所以我想出了一些不同的方法,它能够很好地解决问题。

$arr = array("YD-100 BLACK", "YD-100 GREEN", "YD-100 RED", "YJ-100 BLACK");
//split model number from color
$model = explode(" ",$arr[0])
//find all values that match the model number
$match_values = array_filter($arr, function($val,$key) use (&$model) { return stristr($val, $model[0]);}, ARRAY_FILTER_USE_BOTH);
//returns
//[0] => YD-100 BLACK
//[1] => YD-100 GREEN
//[2] => YD-100 RED

这仅适用于PHP 5.6.0及以上版本。


这与原帖的问题/样本数据/要求不同。 - mickmackusa
@mickmackusa 这是我在谷歌上寻找解决方案时首先看到的,由于之前提到的解决方案都没有帮助到我,所以我不得不想出自己的解决方案。我发布了它,以便其他寻找解决方案的人可以从中受益。 - JJJ
当您遇到一个新问题,并且已有的页面无法解决它时,请提出一个新问题并自己回答。这样可以避免问题偏离主题。在给定页面上发布的答案应该能够解决问题,但是您的答案并没有解决问题。 - mickmackusa
此外,ARRAY_FILTER_USE_BOTH 在这里是无用的,php 手册建议不要使用 strstr() 来检查子字符串是否存在。strstr($arr[0], ' ', true) 应该获取前导子字符串。没有理由通过引用使前导子字符串可修改,因为您从未修改它。 - mickmackusa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接