in_array()和多维数组

287

我使用 in_array() 检查数组中是否存在一个值,如下所示:

$a = array("Mac", "NT", "Irix", "Linux");
if (in_array("Irix", $a)) 
{
    echo "Got Irix";
}

//print_r($a);

但是对于多维数组(如下),我该如何检查该值是否存在于多维数组中?

$b = array(array("Mac", "NT"), array("Irix", "Linux"));

print_r($b);

当处理多维数组时,我是否不应该使用in_array()函数?


1
已接受的解决方案在进行非严格比较时可能会导致意外结果,这是由于 PHP 的类型转换。请参见:https://dev59.com/Hm855IYBdhLWcg3w0H53#48890256 - Paolo
@Paolo 谢谢你的评论。那么解决办法是什么呢?是你刚刚发表的回答吗? - Run
1
我的答案和jwueller的答案都是你问题的正确答案。我提出了一种替代方案,扩展了jwueller的函数,以避免PHP在进行非严格比较时的常见陷阱。 - Paolo
1
var_dump(array_sum(array_map(function ($tmp) {return in_array('NT',$tmp);}, $multiarray)) > 0); 的一句话代码。 - Agnius Vasiliauskas
1
@AgniusVasiliauskas 聪明的解决方案,但如果第一级数组包含一个不是数组的项,则存在问题,例如:$multiarray = array( "Hello", array("Mac", "NT"), array("Irix", "Linux")); - Paolo
1
@Paolo 没有人阻止您根据自己的需求扩展匿名函数 - 在这种情况下,可以在匿名函数中使用 is_array() 函数检查变量 $tmp 是否为数组。如果不是数组,则继续执行不同的方案。 - Agnius Vasiliauskas
24个回答

507

in_array()函数不能在多维数组中使用。您可以编写一个递归函数来实现:

function in_array_r($needle, $haystack, $strict = false) {
    foreach ($haystack as $item) {
        if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) {
            return true;
        }
    }

    return false;
}

使用方法:

$b = array(array("Mac", "NT"), array("Irix", "Linux"));
echo in_array_r("Irix", $b) ? 'found' : 'not found';

1
谢谢。这个函数很优雅!我喜欢它!谢谢。当我运行你的函数时,我的屏幕没有显示任何东西,我怎么知道它返回true还是false?谢谢。 - Run
16
我在寻找能够完成这个任务的工具,你让我免于自己编写,非常感谢 :) - Liam W
1
它运行得很好。那么我们如何搜索和显示数组键呢?例如: $b = array(1 => array("Mac", "NT"), 3 => array("Irix", "Linux")); - Rashad
2
@D.Tate 在 StackOverflow 上的代码采用 cc by-sa 3.0 许可,需要注明来源(请参见页面页脚)。您可以在评论中包含此答案的永久链接。 - jwueller
1
@blamb:这是非常有意义的。这就是使函数递归的原因(类似于print_r())。它会深入所有嵌套的数组来搜索值,直到没有更多的数组可以找到为止。这样,您就可以搜索任意复杂度的数组,而不仅仅是两层深度。 - jwueller
显示剩余11条评论

102

如果您知道要搜索的列,可以使用array_search()和array_column():

$userdb = Array
(
    (0) => Array
        (
            ('uid') => '100',
            ('name') => 'Sandra Shush',
            ('url') => 'urlof100'
        ),

    (1) => Array
        (
            ('uid') => '5465',
            ('name') => 'Stefanie Mcmohn',
            ('url') => 'urlof5465'
        ),

    (2) => Array
        (
            ('uid') => '40489',
            ('name') => 'Michael',
            ('url') => 'urlof40489'
        )
);

if(array_search('urlof5465', array_column($userdb, 'url')) !== false) {
    echo 'value is in multidim array';
}
else {
    echo 'value is not in multidim array';
}

这个想法在 PHP 手册的 array_search() 评论部分中;


34
你也可以尝试使用:in_array('value', array_column($arr, 'active'))。 - ekstro
1
你需要 PHP 5.5+ 才能使用 array_column - m.e.conroy
1
在这个例子中,是否有可能获取匹配的子数组的uid?@ethmz - zipal_
1
这正是我想要的。 - Juned Ansari
1
这是完美的,经过长时间的寻找,我终于找到了这个解决方案! - Rohan Ashik

60

这也可以行。

function in_array_r($item , $array){
    return preg_match('/"'.preg_quote($item, '/').'"/i' , json_encode($array));
}

用法:

if(in_array_r($item , $array)){
    // found!
}

3
聪明,我喜欢这个。我想知道它与foreach循环相比的性能如何。 - James
1
运行得非常顺利。 - kemicofa ghost
1
别误会,我喜欢这种方法来解决这个问题。但是当json_encode一个$array时,如果它有一个与$item匹配的关联键,它将返回一个错误的正匹配。更不用说当字符串本身中有双引号时,可能会无意中匹配到字符串的一部分。我只会在像这个问题这样的小而简单的情况下信任这个函数。 - mickmackusa
请注意,如果$item包含破坏preg_match第一个参数(正则表达式)的字符,则此操作将失败。 - Paolo

35
这样就可以了:
foreach($b as $value)
{
    if(in_array("Irix", $value, true))
    {
        echo "Got Irix";
    }
}

in_array只能在一维数组上操作,因此您需要循环遍历每个子数组并在每个子数组上运行in_array

正如其他人所指出的那样,这仅适用于二维数组。如果您有更多嵌套的数组,则递归版本会更好。请参见其他答案中的示例。


7
这只在一个维度上起作用。你需要创建一个递归函数以检查每个深度。 - metrobalderas
我运行了代码,但出现了错误 - 在C:\ wamp \ www \ 000_TEST \ php \ php.in_array \ index.php的第21行中出现了解析错误 - 错误是if(in_array(“Irix”,$ value))。谢谢。 - Run
@lauthiamkok:在提到的那一行末尾缺少一个 ) - jwueller
谢谢,我修正了我的答案。这就是当我打字太快并且没有重新阅读我的代码时会发生的事情。 - Alan Geleynse
你应该总是将in_array()的第三个参数设置为true。在这里查看原因:https://dev59.com/9Zbfa4cB1Zd3GeqPzNFX - Andreas

27
$userdb = Array
(
    (0) => Array
        (
            ('uid') => '100',
            ('name') => 'Sandra Shush',
            ('url') => 'urlof100'
        ),

    (1) => Array
        (
            ('uid') => '5465',
            ('name') => 'Stefanie Mcmohn',
            ('url') => 'urlof5465'
        ),

    (2) => Array
        (
            ('uid') => '40489',
            ('name') => 'Michael',
            ('url') => 'urlof40489'
        )
);

$url_in_array = in_array('urlof5465', array_column($userdb, 'url'));

if($url_in_array) {
    echo 'value is in multidim array';
}
else {
    echo 'value is not in multidim array';
}

2
虽然这段代码可能回答了问题,但提供有关它如何以及/或为什么解决问题的附加上下文将改善答案的长期价值。 - Donald Duck
4
6年后,它给了我所需的东西。array_column() - NappingRabbit
多维数组的完美答案 - Roshan Sankhe
小技巧:我们还可以使用array_column()函数按值搜索键:$key_product = array_search($featured_prod_id, array_column($PRODUCTS_ARRAY, 'id') ); // 这样就不需要循环来检索条目的键了,在给定的情况下这对我很有意义。 - SNS - Web et Informatique

26

如果你的数组是这样的

$array = array(
              array("name" => "Robert", "Age" => "22", "Place" => "TN"), 
              array("name" => "Henry", "Age" => "21", "Place" => "TVL")
         );

使用此方法

function in_multiarray($elem, $array,$field)
{
    $top = sizeof($array) - 1;
    $bottom = 0;
    while($bottom <= $top)
    {
        if($array[$bottom][$field] == $elem)
            return true;
        else 
            if(is_array($array[$bottom][$field]))
                if(in_multiarray($elem, ($array[$bottom][$field])))
                    return true;

        $bottom++;
    }        
    return false;
}

示例代码:echo in_multiarray("22", $array,"Age");


24

对于多维数组: in_array('needle', array_column($arr, 'key'))

对于一维数组: in_array('needle', call_user_func_array('array_merge', $arr))


1
不错!谢谢 @9ksoft - phaberest
1
array_column()方法不同,call_user_func_array('array_merge')方法还适用于基于索引的子数组,+1。 - user2757283
太棒了!我投票支持这个解决方案。 - Adrian Smith
好的,这个可行;为了减少开销(如果有必要),将__array_column($arr, 'key')__单独放入一个命名的静态变量中,因为它基本上是一个以'key'命名的数字索引数组。 - Ajowi

14

这是一个不错的函数,但在我加入if($found) { break; }elseif之前它对我没用。

function in_array_r($needle, $haystack) {
    $found = false;
    foreach ($haystack as $item) {
    if ($item === $needle) { 
            $found = true; 
            break; 
        } elseif (is_array($item)) {
            $found = in_array_r($needle, $item); 
            if($found) { 
                break; 
            } 
        }    
    }
    return $found;
}

7
自从 PHP 5.6 起,有一个更好、更干净的解决方案来实现原始答案:
使用类似这样的多维数组:
$a = array(array("Mac", "NT"), array("Irix", "Linux"))

我们可以使用展开运算符(splat operator):

展开运算符

return in_array("Irix", array_merge(...$a), true)

如果您有如下的字符串键:

如果您的键是这样的:

$a = array("a" => array("Mac", "NT"), "b" => array("Irix", "Linux"))

为了避免错误 Cannot unpack array with string keys, 您需要使用array_values

return in_array("Irix", array_merge(...array_values($a)), true)

6

您可以将多维数组序列化,然后使用 strpos 函数:

$arr = array(array("Mac", "NT"), array("Irix", "Linux"));

$in_arr = (bool)strpos(serialize($arr),'s:4:"Irix";');

if($in_arr){
    echo "Got Irix!";
}

我所使用的各种文档:


1
这是错误的。如果搜索字符串包含在某个数组值中(将在“mytoll Irixus”中找到“Irix”),则您的函数也会返回true。 - mdunisch
我已经修正了我的回答。@user3351722 - user1846065
这种方法可以解决一个问题,即当不再有唯一值时,并且它是动态的...就像这样$in_arr = (bool)strpos(serialize($user_term_was_downloaded), 's:3:"tid";s:2:"'.$value->tid.'";'); - Anees Hikmat Abu Hmiad
2
@I--I 我认为 Stack Overflow 上没有人会发布代码,如果他们不希望它被分享。随意使用此网站上的任何代码。我通常会在代码片段上方添加一行注释,写上“感谢 Stack Overflow”,然后粘贴我从中找到代码的 URL。 - user1846065
1
有趣的答案,肯定在某些情况下有效,但并非所有情况都适用。 - Michael Mikhjian
显示剩余3条评论

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