【问题标题】:Check if a specific value exists at a specific key in any subarray of a multidimensional array检查多维数组的任何子数组中的特定键是否存在特定值
【发布时间】:2011-10-22 21:09:28
【问题描述】:

我需要在多维数组中搜索任何索引子数组中的特定值。

换句话说,我需要检查多维数组的单列是否有值。如果该值存在于多维数组中的任何位置,我想返回true,否则返回false

$my_array = array(    
    0 =>  array(  
        "name"   => "john",  
        "id"    =>  4  
    ),  
    1   =>  array(  
        "name" =>  "mark",  
        "id" => 152  
    ), 
    2   =>  array(  
        "name" =>  "Eduard",  
        "id" => 152  
    )
);

我想知道检查数组$my_array 是否包含键为“id”的值的最快和最有效的方法。例如,如果id => 152在多维数组中的任何位置,我想要true

【问题讨论】:

    标签: php arrays search multidimensional-array array-column


    【解决方案1】:

    没有什么比一个简单的循环更快的了。你可以混合和匹配一些数组函数来做到这一点,但它们也只是作为一个循环来实现。

    function whatever($array, $key, $val) {
        foreach ($array as $item)
            if (isset($item[$key]) && $item[$key] == $val)
                return true;
        return false;
    }
    

    【讨论】:

      【解决方案2】:

      ** PHP >= 5.5

      你可以用这个

      $key = array_search(40489, array_column($userdb, 'uid'));
      

      假设这个多维数组:

      $userdb=Array
      (
      (0) => Array
          (
              (uid) => '100',
              (name) => 'Sandra Shush',
              (url) => 'urlof100'
          ),
      
      (1) => Array
          (
              (uid) => '5465',
              (name) => 'Stefanie Mcmohn',
              (pic_square) => 'urlof100'
          ),
      
      (2) => Array
          (
              (uid) => '40489',
              (name) => 'Michael',
              (pic_square) => 'urlof40489'
          )
      );
      
      $key = array_search(40489, array_column($userdb, 'uid'));
      

      【讨论】:

      • 为什么不简单地$ids = array_column($array, 'id', 'id'); 然后isset($ids[40489])
      • 嘿,您介意更新您的答案并实施 Elias 的评论吗?
      • 向未来的研究人员澄清$key 可能是0 这是一个虚假值很重要。要知道array_search() 是否找到符合条件的数据,您必须根据需要明确检查$key !== false$key === false
      【解决方案3】:

      这是 Dan Grossman 的答案的更新版本,它将迎合多维数组(我所追求的):

      function find_key_value($array, $key, $val)
      {
          foreach ($array as $item)
          {
              if (is_array($item) && find_key_value($item, $key, $val)) return true;
      
              if (isset($item[$key]) && $item[$key] == $val) return true;
          }
      
          return false;
      }
      

      【讨论】:

      • 是否可以这样做,但不检查特定值?如果key为空返回true,如果key不为空返回false。
      • 如果没有$key的实际值可以传入怎么办?无论键是什么,我都想搜索整个数组。
      • 听起来你只需要 php 函数 'array_search'
      • 因为输入数据被限制在 2 个级别的深度,所以为这个任务实现递归技术是不必要的开销。如果这是一个递归任务(它不是),那么array_walk_recursive() 将只访问叶节点并消除is_array() 检查。
      • 我的数组的层数比 2 多很多 ?
      【解决方案4】:

      最简单的方法是这样的:

      $my_array = array(    
          0 =>  array(  
              "name"   => "john",  
              "id"    =>  4  
          ),  
          1   =>  array(  
              "name" =>  "mark",  
              "id" => 152  
          ), 
          2   =>  array(  
              "name" =>  "Eduard",  
              "id" => 152  
          )
      );
      
      if (array_search(152, array_column($my_array, 'id')) !== FALSE) {
        echo 'FOUND!';
      } else {
        echo 'NOT FOUND!';
      }
      

      【讨论】:

        【解决方案5】:

        如果您必须进行大量“id”查找并且它应该非常快,您应该使用包含所有“id”作为键的第二个数组:

        $lookup_array=array();
        
        foreach($my_array as $arr){
            $lookup_array[$arr['id']]=1;
        }
        

        现在您可以非常快速地检查现有 id,例如:

        echo (isset($lookup_array[152]))?'yes':'no';
        

        【讨论】:

          【解决方案6】:

          @Elias Van Ootegan 在以下评论中提供了一个好的解决方案:

          $ids = array_column($array, 'id', 'id');
          echo isset($ids[40489])?"Exist":"Not Exist";
          

          我试过了,对我有用,谢谢哥们。

          已编辑

          注意:它将在 PHP 5.5+ 中工作

          【讨论】:

          【解决方案7】:

          正如您的问题,这实际上是一个简单的二维数组不是更好吗?看看-

          假设您的二维数组名称 $my_array 和要查找的值是 $id

          function idExists($needle='', $haystack=array()){
              //now go through each internal array
              foreach ($haystack as $item) {
                  if ($item['id']===$needle) {
                      return true;
                  }
              }
              return false;
          }
          

          并称之为:

          idExists($id, $my_array);
          

          如您所见,它实际上只检查 key_name 'id' 的任何内部索引是否具有您的 $value。如果 key_name 'name' 也具有 $value

          ,则此处的其他一些答案也可能为 true

          【讨论】:

          • 这个将成为页面上表现最好的之一,因为它采用了提前返回,并且在检查针头之前不会创建 id 列数据的临时数组。跨度>
          【解决方案8】:

          TMTOWTDI。以下是按复杂程度排列的几种解决方案。

          (以下是关于复杂性的简短入门):O(n) 或“big o”表示 最坏的情况,其中 n 表示数组中的元素数量,o(n) 或“little o" 表示最佳情况。离散数学长话短说,您只需要担心最坏的情况,并确保它不是n ^ 2n!。随着n 的增加,它更多地衡量计算时间的变化,而不是整体计算时间。 Wikipedia has a good article about computational aka time complexity.

          如果经验教会了我什么,那就是花太多时间优化程序的 little-o 显然是在浪费时间,最好把时间花在做某事——任何事情——更好。

          解决方案 0:O(n) / o(1) 复杂性:

          此解决方案具有 1 次比较的最佳情况 - 通过循环进行 1 次迭代,但仅提供匹配值位于数组的位置 0。最坏的情况是它不在数组中,因此必须遍历数组的每个元素。

          foreach ($my_array as $sub_array) {
              if (@$sub_array['id'] === 152) {
                  return true;
              }
          }
          return false;
          

          解决方案 1:O(n) / o(n) 复杂性:

          无论匹配值在哪里,此解决方案都必须循环遍历整个数组,因此它始终是n 遍历数组。

          return 0 < count(
              array_filter(
                  $my_array,
                  function ($a) {
                      return array_key_exists('id', $a) && $a['id'] == 152;
                  }
              )
          );
          

          解决方案 2:O(n log n) / o(n log n) 复杂性:

          哈希插入是log n 的来源; n 哈希插入 = n * log n。最后有一个哈希查找,它是另一个 log n,但它不包括在内,因为这正是离散数学的工作原理。

          $existence_hash = [];
          foreach ($my_array as $sub_array) {
              $existence_hash[$sub_array['id']] = true;
          }
          return @$existence_hash['152'];
          

          【讨论】:

          • array_filter() 的返回值转换为(bool) 将使您不必计算结果或与0 进行比较。 3v4l.org/2dVAu 对于任何正在寻找最有效技术(并且 OP 是)的人,使用 array_filter() 将继续迭代输入数组,即使在找到匹配项之后,这也不是最好的方法。
          • The count() call is an O(1) operation,因此没有使用强制转换进行优化。即使你把它写成一个短路的for循环,最坏的情况仍然是O(n),因为$my_array中不存在ID。
          • 通过转换为(bool)array_filter()的返回值没有函数调用和条件比较,因此转换为布尔类型更加直接和简洁。 DanGrossman 的技术(尽管我会为所有语言结构使用花括号)将是表现最好的,因为它执行有条件的提前返回/中断。我相信你已经知道了;我只是为研究人员说明这个事实。请在您的回答中添加解释,以更好地向新用户发布行为。
          【解决方案9】:

          我看到这篇文章也想做同样的事情,并想出了我自己的解决方案,我想为这个页面的未来访问者提供(并看看这样做是否会出现我没有预见到的任何问题)。

          如果你想得到一个简单的truefalse 输出,并且想用一行代码而不用函数或循环来做到这一点,你可以序列化数组,然后使用stripos 搜索值:

          stripos(serialize($my_array),$needle)

          这似乎对我有用。

          【讨论】:

            【解决方案10】:

            你可以只用两个参数来使用它

            function whatever($array, $val) {
                foreach ($array as $item)
                    if (isset($item) && in_array($val,$item))
                        return 1;
                return 0;
            }
            

            【讨论】:

              【解决方案11】:

              我不知道这对性能来说是好是坏,但这里有一个替代方案:

              $keys = array_map(function($element){return $element['id'];}, $my_array);
              $flipped_keys = array_flip($keys);
              if(isset($flipped_keys[40489]))
              {
                  // true
              }
              

              【讨论】:

              • 你可能也对array_column感兴趣php.net/array_column
              • 我看到了,很多人都建议过,我一个人尝试过,直到我看到上面的 Manuel 才能让它工作。 $key = array_search(40489, array_column($userdb, 'uid'));。我已经找到了我的解决方案,只是想我会分享它。不过,array_search 和 array_column 组合效果很好。
              • array_column 和 array_flip 工作相同。它只是作为提示仅供参考,array_map 部分可以用它替换,其余部分相同。就我个人而言,我不会将它与 array_search 结合起来,但更像是你对 array_flip 所做的。
              【解决方案12】:

              isset 与 array_key_exits 之间的不同 What's the difference between isset() and array_key_exists()?

              == vs === How do the PHP equality (== double equals) and identity (=== triple equals) comparison operators differ?

              的区别
              function specificValue(array $array,$key,$val) {
                  foreach ($array as $item)
                      if (array_key_exits($item[$key]) && $item[$key] === $val)
                          return true;
                  return false;
              }
              

              【讨论】:

                【解决方案13】:

                试试下面的代码。它应该适用于任何类型的多维数组搜索。

                这里可以看到LIVE DEMO EXAMPLE

                function multi_array_search($search_for, $search_in) {
                    foreach ($search_in as $element) {
                        if ( ($element === $search_for) ){
                            return true;
                        }elseif(is_array($element)){
                            $result = multi_array_search($search_for, $element);
                            if($result == true)
                                return true;
                        }
                    }
                    return false;
                }
                

                【讨论】:

                • 请注意,使用递归不仅是不必要的开销,还会对第一级元素进行不必要的检查。证明递归对于这个问题是一个不好的选择。 3v4l.org/Aua2W
                【解决方案14】:
                function checkMultiArrayValue($array) {
                        global $test;
                        foreach ($array as $key => $item) {
                
                            if(!empty($item) && is_array($item)) {
                                checkMultiArrayValue($item);
                            }else {
                                if($item)
                                 $test[$key] = $item;
                
                            }
                        }
                        return $test;   
                    }
                
                 $multiArray = array(    
                                0 =>  array(  
                                      "country"   => "",  
                                      "price"    => 4,  
                                      "discount-price" => 0,  
                               ),);
                
                $test = checkMultiArrayValue($multiArray);
                echo "<pre>"
                print_r($test);
                

                将返回具有索引和值的数组

                【讨论】:

                • 此任务不会受益于递归技术。这个仅代码的答案对于教育/授权成千上万的未来研究人员几乎没有什么作用。当您发布答案时,请务必用简单的英语解释它是如何工作的,以及它与该特定问题的其他答案相比有什么优势。
                【解决方案15】:

                我编写了以下函数来确定多维数组是否部分包含某个值。

                function findKeyValue ($array, $needle, $value, $found = false){
                    foreach ($array as $key => $item){
                        // Navigate through the array completely.
                        if (is_array($item)){
                            $found = $this->findKeyValue($item, $needle, $value, $found);
                        }
                
                        // If the item is a node, verify if the value of the node contains
                        // the given search parameter. E.G.: 'value' <=> 'This contains the value'
                        if ( ! empty($key) && $key == $needle && strpos($item, $value) !== false){
                            return true;
                        }
                    }
                
                    return $found;
                }
                

                这样调用函数:

                $this->findKeyValue($array, $key, $value);
                

                【讨论】:

                • 没有理由为此任务使用递归。输入数组只有两层深。这是不必要的卷积,不应用于此问题。
                猜你喜欢
                • 2018-04-16
                • 2013-10-25
                • 1970-01-01
                • 2011-05-29
                • 1970-01-01
                • 2013-03-15
                • 1970-01-01
                • 2012-11-16
                • 2018-06-15
                相关资源
                最近更新 更多