递归搜索多维数组时获取第一个匹配键的值

问题描述 投票:0回答:8
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 recursion multidimensional-array filtering
8个回答
57
投票

也许对于旧版本的 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
}

20
投票
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


6
投票

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

0
投票

试试这个:

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

0
投票

我刚刚经历过类似的问题,这对我有用:

    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 条件。有任何疑问或批评都非常欢迎,干杯!


0
投票

我最近在处理 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);


0
投票

如果键重复并且只返回第一个值,上面的最佳解决方案会错过这种情况,这里我得到数组中的所有值:(Demo)

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

0
投票

这是我的解决方案:

function find_value_by_key($key,$array) {
    $data = array('key'=>$key,'ret'=>array());
    array_walk_recursive($array,function($v,$k) use (&$data) {
        if ($k==$data['key'])
            $data['ret'][] = $v;
    },$data);
    return $data['ret'];
}

返回找到的值的数组,如果未找到键,则返回空数组。

如果您只需要返回它找到的第一个值,您可以使用:

function find_value_by_key($key,$array) {
        $data = array('key'=>$key);
        array_walk_recursive($array,function($v,$k) use (&$data) {
            if (isset($data['ret']))
                return;
            if ($k==$data['key'])
                $data['ret'] = $v;
        },$data);
        return $data['ret']?:false;
}

返回找到的第一个值。

如果未找到密钥,则返回

false

以下数组示例:

$数组=数组( 0 => 'A', 1 => 'B', 2 => 'C', 'foo' => '酒吧', 'mykey' => '哈哈', '测试' => 数组( '例子' => '哈哈', 'mykey' => '呼呼', ), '随机' => 数组( 大批( 'mykey' => '呵呵', 'notmykey' => 'topkek', ), 大批( 'mykey' => '呵呵', 'notmykey' => 'topkek', ), ), );

第一个函数将返回

["haha","hoho","hehe","huhu"]
,第二个函数将返回
"haha"

© www.soinside.com 2019 - 2024. All rights reserved.