【问题标题】:Search for a key in an array, recursively递归搜索数组中的键
【发布时间】:2011-04-27 21:31:31
【问题描述】:
private function find($needle, $haystack) {
    foreach ($haystack as $name => $file) {
        if ($needle == $name) {
            return $file;
        } else if(is_array($file)) { //is folder
            return $this->find($needle, $file); //file is the new haystack
        }               
    }

    return "did not find";
}

嘿,此方法在关联数组中搜索特定键并返回与其关联的值。递归有问题。有什么线索吗?

【问题讨论】:

  • 你怎么不知道它在什么级别?

标签: php arrays search recursion


【解决方案1】:

我最近在处理 Yii2 查询对象时遇到了同样的问题。

您的函数不起作用的原因是返回操作在这里不起作用。只需传递一个引用参数来存储值,然后做任何你想做的事情。

如您所见,这是一个简单的 PHP 函数,不依赖任何库。所以我认为上面列出的所有答案都值得一提。

function array_search_by_key_recursive($needle, array $haystack, &$return)
{
   foreach ($haystack as $k => $v) {
      if (is_array($v)) {
        array_search_by_key_recursive($needle, $v, $return);
      } else {
        if($k === $needle){
           $return = $v;
        }
      }
   }
}

array_search_by_key_recursive($needle, array $haystack, $return);

print_r($return);

【讨论】:

    【解决方案2】:

    我刚刚遇到了类似的问题,这对我有用:

        function searchArrayByKey($haystack, $needle, $i = 0) {
         $result = array();
         foreach($haystack as $key => $value) {
           if (is_array($value)) {
             $nextKey = searchArrayByKey($value, $needle);
             if ($nextKey) {
               return $nextKey;
             }
           }
           if (is_array($value) && array_key_exists($needle, $value)) {
             $result[$i++] = $value[$needle];
           }
         }
         if (empty($result)) {
           return false;
         } else {
           return $result;
         }
       }
    

    这将返回一个数组,其中包含它在多维数组中找到的所有匹配键的值。我用电子邮件 API 动态生成的数组对此进行了测试。在多个匹配的情况下,您只需要创建一个简单的 foreach 循环即可对数组进行任意排序。

    我注意到我犯的主要错误是在我应该使用 if-if 条件时使用了 if-ifelse 条件。任何问题或批评都非常欢迎,干杯!

    【讨论】:

      【解决方案3】:

      也许它有点矫枉过正,但使用 RecursiveIterators 很有趣:)

      更新:也许它对旧版本的 PHP 来说太过分了,但是对于 >=5.6(特别是 7.0)我会毫无疑问地完全使用它。

      function recursiveFind(array $haystack, $needle)
      {
          $iterator  = new RecursiveArrayIterator($haystack);
          $recursive = new RecursiveIteratorIterator(
              $iterator,
              RecursiveIteratorIterator::SELF_FIRST
          );
          foreach ($recursive as $key => $value) {
              if ($key === $needle) {
                  return $value;
              }
          }
      }
      

      更新:此外,从 PHP 5.6 开始,使用生成器,您可以轻松地遍历所有通过过滤器的元素,而不仅仅是第一个:

      function recursiveFind(array $haystack, $needle)
      {
          $iterator  = new RecursiveArrayIterator($haystack);
          $recursive = new RecursiveIteratorIterator(
              $iterator,
              RecursiveIteratorIterator::SELF_FIRST
          );
          foreach ($recursive as $key => $value) {
              if ($key === $needle) {
                  yield $value;
              }
          }
      }
      
      // Usage
      foreach (recursiveFind($haystack, $needle) as $value) {
          // Use `$value` here
      }
      

      【讨论】:

      • 谢谢。这救了我。如果您不需要对密钥进行严格比较,请记住将===更改为==
      • 注意,如果key在递归中出现多次,这里只会获取第一个的值。为了让他们都像这样修改它:function recursiveFind(array $array, $needle) { $iterator = new RecursiveArrayIterator($array); $recursive = new RecursiveIteratorIterator( $iterator, RecursiveIteratorIterator::SELF_FIRST ); $return = []; foreach ($recursive as $key => $value) { if ($key === $needle) { $return[] = $value; } } return $return; }
      • 在 PHP 5.6 之后我会为此使用生成器,调用 yield 而不是 return
      • 那会是@xPheRe
      【解决方案4】:

      上面的最佳解决方案错过了如果键重复并且只返回第一个值的情况,这里我将所有值都放在一个数组中:

      function recursiveFind(array $array, $needle) {
        $iterator = new RecursiveArrayIterator($array);
        $recursive = new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::SELF_FIRST);
        $return = [];
        foreach ($recursive as $key => $value) {
          if ($key === $needle) {
            $return[] = $value;
          }
        } 
        return $return;
      }
      

      【讨论】:

        【解决方案5】:

        xPheRe 提供的答案非常有帮助,但在我的实现中并没有完全解决问题。我们的数据结构中有多个嵌套的关联数组,并且任何给定的键都可能多次出现。

        为了满足我们的目的,我需要实现一个在遍历整个结构时更新的持有者数组,而不是在第一次匹配时返回。真正的工作是由另一张海报提供的,但我想说声谢谢并分享我必须涵盖的最后一步。

        public function recursiveFind(array $array, $needle)
        {
            $iterator  = new RecursiveArrayIterator($array);
            $recursive = new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::SELF_FIRST);
            $aHitList = array();
            foreach ($recursive as $key => $value) {
                if ($key === $needle) {
                    array_push($aHitList, $value);
                }
            }
            return $aHitList;
        }
        

        【讨论】:

          【解决方案6】:

          试试这个:

          array_walk_recursive(
              $arrayToFindKey, 
              function($value, $key, $matchingKey){
                  return (strcasecmp($key, $matchingKey) == 0)? true : false;
              }
              , 'matchingKeyValue'
          );
          

          【讨论】:

          • array_walk_recursive 可能是 php 最没用的函数之一。它将跳过所有子数组,因此如果您的 $key 是另一个数组的键,您将找不到它
          【解决方案7】:
          function array_search_key( $needle_key, $array ) {
            foreach($array AS $key=>$value){
              if($key == $needle_key) return $value;
              if(is_array($value)){
                if( ($result = array_search_key($needle_key,$value)) !== false)
                  return $result;
              }
            }
            return false;
          } 
          

          这会起作用的!

          你需要停止递归深度搜索,返回 false 然后在函数中检查它。

          您可以在此链接中找到更多函数示例(例如使用 RecursiveArrayIterator 等): http://php.net/manual/en/function.array-search.php

          【讨论】:

          • 如果键值为'0'/零,则失败。然后使用下面的一个:fn 'recursiveFind'。
          猜你喜欢
          • 2015-04-12
          • 1970-01-01
          • 2013-05-12
          • 2012-09-16
          • 1970-01-01
          • 1970-01-01
          • 2018-01-10
          • 2018-03-08
          相关资源
          最近更新 更多