【问题标题】:array_walk_recursive with array?array_walk_recursive 与数组?
【发布时间】:2014-08-24 13:55:58
【问题描述】:

我有一个菜单数组,它是一个多维数组,我想对每个项目做一些事情,所以我尝试了 array_walk_recursive。这是菜单:

$menu = array(
    array(
        'name'=>'a',
        'url'=>'b',
    ),
    array(
        'name'=>'c',
        'url'=>'d',
        'children'=>array(
            array(
                'name'=>'e',
                'url'=>'f'
            )
        )
    )
);

但是 array_walk_recursive 只让我处理每个元素,而不是数组。

array_walk_recursive($menu, function(&$item){
    var_dump($item);//return a;b;c;d;e;f;g
});

我想要的是这样的:

array_walk_recursive_with_array($menu, function(&$item){
    var_dump($item);//return array('name'=>'a','url'=>'b');a;b;array('name'=>'c',...);c;d;...
    if(is_array($item) && isset($item['name'])){
        // I want to do something with the item.
    }
})

有没有PHP原生函数实现?

【问题讨论】:

  • 可能是RecursiveArrayIterator的情况
  • array_walk_recursive 是修改数组。在执行array_walk_recursive 之后,您希望您的$menu 如何。

标签: php arrays recursion


【解决方案1】:

根据array_walk_recursive documentation,无法获取内部数组键。 满足您需求的一种方法是使用 array_walk 并创建您自己的递归。

function HandleArray(&$value){
    if(is_array($value)){
        //Do something with all array
        array_walk($value,'HandleArray');
    }
    else{
       //do something with your scalar value
    }
}
array_walk(array($your_array),'HandleArray');

【讨论】:

  • 对。根据 PHP 文档:“任何包含数组的键都不会传递给函数。”为什么会这样,超出了我的范围。对于名为“recursive”的函数来说,这似乎违反直觉。
  • @mach128x 当内部的数组是自引用的时,递归地保存数组的遍历数组键会爆炸。您至少需要一个 maxDepth 参数来停止无限递归。如果输入数组来自未知来源,上面的 HandleArray() 示例也需要防止无限递归。
【解决方案2】:

@artragis 示例中使用array_walk() 的无限递归保护似乎是必要的。 一个 ArrayHelper 类示例,用于将 给定数组 简化为 给定数组键 的数组值:

class ArrayHelper {
    /**
     * arrayFlattenToKeyValues - Like finding keys with array_walk_recursive()
     *   without the restriction "Any key that holds an array will not be passed to the function"
     * @see https://www.php.net/manual/en/function.array-walk-recursive.php#refsect1-function.array-walk-recursive-examples
     * @param array $deepArray
     * @param string $fromKey
     * @param int $maxDepth default = 10
     * @param array $accumulator default = []
     *
     * @return array
     */
    public static function arrayFlattenToKeyValues(
        array $deepArray,
        string $fromKey,
        int $maxDepth = 10,
        array $accumulator = []
    ): array {
        array_walk($deepArray, function ($value, $key) use (&$accumulator, $fromKey, $maxDepth) {
            if ($key === $fromKey) {
                $accumulator[] = $value;
            }
            if ($maxDepth > 0 && is_array($value)) {
                $accumulator = self::arrayFlattenToKeyValues($value, $fromKey, $maxDepth - 1, $accumulator);
            }
        });

        return $accumulator;
    }
}

这可能会被改进、简化或以不同的方式完成;请做!

【讨论】:

    【解决方案3】:

    您希望在每次遇到包含name 键的数组时递归搜索数组并执行一些操作

    为了演示,这里有一个示例数组,其中包含一个非限定子数组 ($array[1]) 和三个限定子数组($array[0]$array[2]$array[2]['children'])。

    $array = [
        [
            'name' => 'a',
            'url' => 'b',
        ],
        [
            'no-name' => 'foo',
        ],
        [
            'name' => 'c',
            'url' => 'd',
            'children' => [
                [
                    'name' => 'e',
                    'url' => 'f'
                ]
            ]
        ]
    ];
    

    要处理数组,递归访问数据结构中的每个节点。遇到数组时,请使用isset()(或array_key_exists(),如果您需要尊重潜在的null 值)来检查该数组是否符合您想要的操作。

    下面是一个脚本,它将使用限定规则执行递归技术,并在满足规则时添加一个新元素。 & 用于两个地方,表示应该“通过引用修改”变量——这使得数据变异在自定义函数调用范围之外可用。

    代码:(Demo)

    function recurseAll(&$node) {
        if (is_array($node)) {
            if (isset($node['name'])) {
                // do something with the qualifying array...
                $node[] = 'push a new element into array level';
            }
            foreach ($node as &$childNode) {
                recurseAll($childNode);
            }
        }
    }
    
    recurseAll($array);
    var_export($array);
    

    输出:

    array (
      0 => 
      array (
        'name' => 'a',
        'url' => 'b',
        0 => 'push a new element into array level',      // added element to $array[0]
      ),
      1 => 
      array (                                            // didn't qualify
        'no-name' => 'foo',
      ),
      2 => 
      array (
        'name' => 'c',
        'url' => 'd',
        'children' => 
        array (
          0 => 
          array (
            'name' => 'e',
            'url' => 'f',
            0 => 'push a new element into array level', // added element to $array[2]['children']
          ),
        ),
        0 => 'push a new element into array level',     // added element to $array[2]
      ),
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-16
      • 2021-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-10
      相关资源
      最近更新 更多