递归搜索数组中的键

Posted

技术标签:

【中文标题】递归搜索数组中的键【英文标题】: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";

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

【问题讨论】:

你怎么不知道它在什么级别? 【参考方案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'。

以上是关于递归搜索数组中的键的主要内容,如果未能解决你的问题,请参考以下文章

PHP - 当给定子键名时,递归地将每个数组元素的键设置为子元素的值

C中的递归未排序数组搜索算法?

递归过滤/减少嵌套对象

使用递归搜索整数数组中元素的所有组合

如何创建一个实现递归二进制搜索的循环来搜索数组中的n个数字? JAVA

字符串数组中字符串(多个实例)的递归二进制搜索 - C#