in_array() 和多维数组

Posted

技术标签:

【中文标题】in_array() 和多维数组【英文标题】:in_array() and multidimensional array 【发布时间】:2011-05-06 21:54:15 【问题描述】:

我使用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()

【问题讨论】:

接受的解决方案效果很好,但由于 php 的类型杂乱,在进行非严格比较时可能会导致意外结果。见:***.com/a/48890256/1579327 jwueller 的答案和我的答案都是您问题的正确答案。我提出了一个扩展 jwueller 函数的替代解决方案,以避免在进行非严格比较时由于 PHP 的类型杂乱而导致的常见错误。 一个班轮:var_dump(array_sum(array_map(function ($tmp) return in_array('NT',$tmp);, $multiarray)) > 0); @AgniusVasiliauskas 聪明的解决方案,但如果第一级数组包含一个不是数组的项目,例如:$multiarray = array( "Hello", array("Mac", "NT"), array("Irix", "Linux")); @Paolo 没有人会阻止您根据需要扩展匿名函数 - 在这种情况下,如果变量 $tmp 是具有 is_array() 函数的数组,则添加检查匿名函数。如果不是数组 - 继续不同的场景。 【参考方案1】:

我发现以下解决方案的代码不是很干净,但它可以工作。它用作递归函数。

function in_array_multi( $needle, $array, $strict = false ) 
  foreach( $array as $value )  // Loop thorugh all values
    // Check if value is aswell an array
    if( is_array( $value )) 
      // Recursive use of this function
      if(in_array_multi( $needle, $value )) 
        return true; // Break loop and return true
      
     else 
      // Check if value is equal to needle
      if( $strict === true ) 
        if(strtolower($value) === strtolower($needle)) 
          return true; // Break loop and return true
        
      else 
        if(strtolower($value) == strtolower($needle)) 
          return true; // Break loop and return true
        
      
    
  

  return false; // Nothing found, false

【讨论】:

【参考方案2】:

由于 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"))

您必须使用array_values 以避免错误Cannot unpack array with string keys

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

【讨论】:

【参考方案3】:

我使用这种方法适用于任意数量的嵌套,不需要破解

<?php
    $blogCategories = [
        'programing' => [
            'golang',
            'php',
            'ruby',
            'functional' => [
                'Erlang',
                'Haskell'
            ]
        ],
        'bd' => [
            'mysql',
            'sqlite'
        ]
    ];
    $it = new RecursiveArrayIterator($blogCategories);
    foreach (new RecursiveIteratorIterator($it) as $t) 
        $found = $t == 'Haskell';
        if ($found) 
           break;
        
    

【讨论】:

【参考方案4】:

我找到了非常小的简单解决方案:

如果你的数组是:

Array
(
[details] => Array
    (
        [name] => Dhruv
        [salary] => 5000
    )

[score] => Array
    (
        [ssc] => 70
        [diploma] => 90
        [degree] => 70
    )

)

那么代码会是这样的:

 if(in_array("5000",$array['details']))
             echo "yes found.";
         
     else 
             echo "no not found";
          

【讨论】:

【参考方案5】:

对于多维儿童: in_array('needle', array_column($arr, 'key'))

对于一维儿童: in_array('needle', call_user_func_array('array_merge', $arr))

【讨论】:

整洁!谢谢@9ksoft array_column() 方法不同,call_user_func_array('array_merge') 方法也适用于基于索引的子数组,+1 太棒了!我投票支持这个解决方案。 很好,这行得通;并且为了减少开销(如果重要的话),将 array_column($arr, 'key') 隔离到一个命名的静态变量中,因为它基本上是一个名为 'key' 的数字索引数组; 【参考方案6】:

这也行。

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

用法:

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

【讨论】:

聪明,我喜欢这个。我想知道与foreach 循环相比性能如何。 工作就像一个魅力。 别误会,我喜欢这种方法。但是,当 json_encoding 具有与 $item 匹配的关联键的 $array 时,它将返回误报匹配。更不用说当字符串本身有双引号时可能无意中匹配字符串的一部分。我只会在像这个问题这样的小/简单情况下相信这个功能。 请注意,如果$item 包含破坏preg_match 的第一个参数(正则表达式)的字符,这将失败【参考方案7】:

jwueller

accepted solution(在撰写本文时)
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;

完全正确,但在进行弱比较时可能会出现意外行为(参数$strict = false)。

由于 PHP 在比较不同类型的值时会出现类型混淆

"example" == 0

0 == "example"

评估true,因为"example" 被转换为int 并转换为0

(见Why does PHP consider 0 to be equal to a string?)

如果这不是所需的行为,在进行非严格比较之前将数值转换为字符串会很方便:

function in_array_r($needle, $haystack, $strict = false) 
    foreach ($haystack as $item) 

        if( ! $strict && is_string( $needle ) && ( is_float( $item ) || is_int( $item ) ) ) 
            $item = (string)$item;
        

        if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) 
            return true;
        
    

    return false;

【讨论】:

【参考方案8】:
$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';

【讨论】:

虽然此代码可能会回答问题,但提供有关它如何和/或为什么解决问题的额外上下文将提高​​答案的长期价值。 6 年后,它给了我我需要的东西。 array_column() 多维数组的完美答案【参考方案9】:

你可以这样使用

$result = array_intersect($array1, $array2);
print_r($result);

http://php.net/manual/tr/function.array-intersect.php

【讨论】:

【参考方案10】:

我正在寻找一个函数,它可以让我在数组 (haystack) 中搜索字符串和数组(如针),所以我添加到 answer by @jwueller。

这是我的代码:

/**
 * Recursive in_array function
 * Searches recursively for needle in an array (haystack).
 * Works with both strings and arrays as needle.
 * Both needle's and haystack's keys are ignored, only values are compared.
 * Note: if needle is an array, all values in needle have to be found for it to
 * return true. If one value is not found, false is returned.
 * @param  mixed   $needle   The array or string to be found
 * @param  array   $haystack The array to be searched in
 * @param  boolean $strict   Use strict value & type validation (===) or just value
 * @return boolean           True if in array, false if not.
 */
function in_array_r($needle, $haystack, $strict = false) 
     // array wrapper
    if (is_array($needle)) 
        foreach ($needle as $value) 
            if (in_array_r($value, $haystack, $strict) == false) 
                // an array value was not found, stop search, return false
                return false;
            
        
        // if the code reaches this point, all values in array have been found
        return true;
    

    // string handling
    foreach ($haystack as $item) 
        if (($strict ? $item === $needle : $item == $needle)
            || (is_array($item) && in_array_r($needle, $item, $strict))) 
            return true;
        
    
    return false;

【讨论】:

【参考方案11】:

我相信你现在可以使用array_key_exists:

<?php
$a=array("Mac"=>"NT","Irix"=>"Linux");
if (array_key_exists("Mac",$a))
  
  echo "Key exists!";
  
else
  
  echo "Key does not exist!";
  
?>

【讨论】:

【参考方案12】:

这是我的提议基于 json_encode() 解决方案

不区分大小写选项 返回计数而不是 true 数组中的任意位置(键和值)

如果没有找到单词,它仍然返回 0 等于 false

function in_array_count($needle, $haystack, $caseSensitive = true) 
    if(!$caseSensitive) 
        return substr_count(strtoupper(json_encode($haystack)), strtoupper($needle));
    
    return substr_count(json_encode($haystack), $needle);

希望对你有帮助。

【讨论】:

请注意,此函数也匹配子字符串:例如 0010000loHello。此外,如果针包含json_encode 转义的任何字符,例如双引号,则会失败。 当然这取决于你会做什么,但对我来说,这个解决方案执行速度很快,就足够了。【参考方案13】:

这样就可以了:

foreach($b as $value)

    if(in_array("Irix", $value, true))
    
        echo "Got Irix";
    

in_array 仅对一维数组进行操作,因此您需要遍历每个子数组并在每个子数组上运行 in_array

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

【讨论】:

但是,这只适用于一维。您必须创建一个递归函数才能检查每个深度。 我运行了代码,但它有一个错误 - Parse error: parse error in C:\wamp\www\000_TEST\php\php.in_array\index.php 在第 21 行 - 这是 if( in_array("Irix", $value) 谢谢。 @lauthiamkok:在上述行的末尾缺少一个) 谢谢,我修正了我的答案。当我输入太快并且不重新阅读我的代码时,就会发生这种情况。 您应该始终调用in_array(),并将第三个参数设置为true。在这里查看原因:***.com/questions/37080581/…【参考方案14】:

如果您知道要搜索哪一列,则可以使用 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() 的 cmets 部分;

【讨论】:

你也可以试试:in_array('value', array_column($arr, 'active')) array_column 需要 PHP 5.5+ 本例中是否可以获取到匹配子数组的uid? @ethmz 这正是我想要的 找了好久这个解决方案终于完美了!【参考方案15】:

您总是可以序列化您的多维数组并执行strpos

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

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

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

我用过的各种文档:

strpos() serialize() Type Juggling or (bool)

【讨论】:

错了。如果搜索字符串包含在某个数组值中(将在“mytoll Irixus”中找到“Irix”),您的函数也会返回 true。 我已经修正了我的答案。 @user3351722 这种方式可以在没有更多人(唯一的vale)时解决问题,并且它是动态的..就像这样 $in_arr = (bool)strpos(serialize($user_term_was_downloaded), 's: 3:"tid";s:2:"'.$value->tid.'";'); @I--我认为如果 Stack Overflow 上的任何人不想共享代码,他们不会发布代码。随意使用本网站上的任何代码做任何事情。我通常在代码 sn-p 上方添加一条注释,上面写着“感谢 Stack Overflow”,然后粘贴我从中找到代码的 URL。 有趣的答案,在某些情况下肯定有效,但不是全部。【参考方案16】:

array_search 呢?根据https://gist.github.com/Ocramius/1290076 ..

似乎它比 foreach 快得多
if( array_search("Irix", $a) === true) 

    echo "Got Irix";

【讨论】:

实际上 array_search 不是递归的,所以这不起作用。我希望它确实如此,因为它是如此干净和简单。 php.net/manual/en/function.array-search.php【参考方案17】:

较短的版本,用于基于数据库结果集创建的多维数组。

function in_array_r($array, $field, $find)
    foreach($array as $item)
        if($item[$field] == $find) return true;
    
    return false;


$is_found = in_array_r($os_list, 'os_version', 'XP');

如果 $os_list 数组在 os_version 字段中包含“XP”,将返回。

【讨论】:

【参考方案18】:

它也可以首先从原始数组创建一个新的一维数组。

$arr = array("key1"=>"value1","key2"=>"value2","key3"=>"value3");

foreach ($arr as $row)  $vector[] = $row['key1'];

in_array($needle,$vector);

【讨论】:

【参考方案19】:

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';

【讨论】:

谢谢。功能优雅!爱它!谢谢。当我运行你的函数时,我怎么知道它返回 true 或 false,因为我的屏幕没有显示任何内容?谢谢。 我一直在寻找可以做到这一点的东西,你只是让我免于编写自己的东西 :) 效果很好。那么我们如何搜索和显示数组键呢?例如:$b = array(1 => array("Mac", "NT"), 3 => array("Irix", "Linux")); @D.Tate *** 上的代码在cc by-sa 3.0 下获得许可,需要注明出处(参见页脚)。您可以在此答案的永久链接中添加评论。 @blamb:这是故意的。这就是使函数递归的原因(例如,_r,类似于print_r())。它下降到所有嵌套数组中以搜索该值,直到找不到更多数组为止。通过这种方式,您可以搜索任意复杂度的数组,而不仅仅是两层深度。【参考方案20】:

请尝试:

in_array("irix",array_keys($b))
in_array("Linux",array_keys($b["irix"])

我不确定是否需要,但这可能适合您的要求

【讨论】:

如何搜索数组键? $b 的数组键只是整数...在这些数组中没有指定的键...而array_keys($b["irix"]) 只会抛出错误,因为$b["irix"] 不存在。【参考方案21】:

如果你的数组是这样的

$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");

【讨论】:

【参考方案22】:

很棒的功能,但在我将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;

【讨论】:

【参考方案23】:

这是我在php manual for in_array 中找到的第一个此类函数。评论部分的功能并不总是最好的,但如果它不能起到作用,你也可以在那里查看:)

<?php
function in_multiarray($elem, $array)
    
        // if the $array is an array or is an object
         if( is_array( $array ) || is_object( $array ) )
         
             // if $elem is in $array object
             if( is_object( $array ) )
             
                 $temp_array = get_object_vars( $array );
                 if( in_array( $elem, $temp_array ) )
                     return TRUE;
             

             // if $elem is in $array return true
             if( is_array( $array ) && in_array( $elem, $array ) )
                 return TRUE;


             // if $elem isn't in $array, then check foreach element
             foreach( $array as $array_element )
             
                 // if $array_element is an array or is an object call the in_multiarray function to this element
                 // if in_multiarray returns TRUE, than return is in array, else check next element
                 if( ( is_array( $array_element ) || is_object( $array_element ) ) && $this->in_multiarray( $elem, $array_element ) )
                 
                     return TRUE;
                     exit;
                 
             
         

         // if isn't in array return FALSE
         return FALSE;
    
?>

【讨论】:

elusive 的解决方案更好,因为它只适用于数组

以上是关于in_array() 和多维数组的主要内容,如果未能解决你的问题,请参考以下文章

如何理解JS多维数组

第34课 多维数组和多维指针

php计算多维数组某个值的和

JS----使用归递获取多维数组中的某列值

多维数组

PHP中多维数组的问题