如何让array_walk_recursive访问每个节点


How to make array_walk_recursive visit every node?

我有一个递归$data结构,我需要修改。被视为$item的每个节点都应获得一个添加值为 $value 的属性。我尝试过的事情(以及它们是如何失败的)是:

  • array_walk_recursive:仅访问叶节点。
  • 堆栈/队列
  • :我无法修改原始结构,而只是更改了堆栈/队列上的副本。
  • 循环
  • :如果没有堆栈/队列方法,我需要知道嵌套级别并编写大量嵌套循环。
  • array_map:我未能编写适当的递归回调,因为$value的值不是静态的,而是先前代码的结果。因此,它必须以某种方式"进入"回调。由于use仅适用于匿名函数,因此我没有设法编写递归函数。
  • 循环和递归函数:这个类似问题的答案失败了,原因与array_map方法相同。

我在代码中的情况类似于此示例:

<?php
$value = 'example';
$data = array(
    'foo' => 'bar'
    'items' => array(
        array(
            'foo' => 'bar',
            'items' => array(
                array('foo' => 'bar')
            )
        )
    )
);
// do this recursively to every member of an 'items' property:
$item['baz'] = $value;

你能想到一个不同的方法或帮助我理顺我迄今为止失败的方法之一吗?

更新

我尝试过的一些代码不起作用:

// Parse error:  syntax error, unexpected 'use' (T_USE), expecting '{'
function do (&$item) use ($value) {
    $item['baz'] = $value;
    foreach ($item['items'] as $next) {
        do($next);
    }
}
// Undefined variable: value
function do (&$item) {
    $item['baz'] = $value;
    foreach ($item['items'] as $next) {
        do($next);
    }
}
foreach ($data['items'] as $item) {
    do($item);
}

现在有效(不过,我不希望传递$value参数):

function do (&$item, $value) {
    $item['baz'] = $value;
    foreach ($item['items'] as &$next) {
        do($next, $value);
    }
}
foreach ($data['items'] as &$item) {
    do($item, $value);
}

检查此代码以获取每个键和值:

<?php
error_reporting(0);
$value = 'example';
$data = array(
    'foo' => 'bar',
    'items' => array( array( 'foo' => 'bar','items' => array(array('foo' => 'bar') ) ) )
);

$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($data));
  foreach ($iterator as $k => $v) {
        echo $k.'=>'.$v;
        echo '</br>';
  }
?>

格式是必要的,但不足以满足最小编辑长度。所以我添加了这个原本无用的文本。

以下递归函数对我有用。请注意,它还需要在 foreach 循环中通过引用传递参数:

$value = 'example';
function do (&$item, $value) {
    $item['baz'] = $value;
    foreach ($item['items'] as &$next) {
        do($next, $value);
    }
}
foreach ($data['items'] as &$item) {
    do($item, $value);
}

我使用这种方法:

<?php
/**
 * @param array $arr
 * @param callable $callback
 * @param array $options
 *
 *
 * Example:
 * (this will add the link property to every node in the array recursively)
 *
 *
 * $linkFmt = "/mylink/{type}/{slug}";
 * ArrayTool::updateNodeRecursive($ret, function (array &$row) use ($linkFmt) {
 *      $row['link'] = str_replace([
 *          "{type}",
 *          "{slug}",
 *      ], [
 *          $row['type'],
 *          $row['slug'],
 *          ], $linkFmt);
 * });
 *
 *
 *
 *
 */
public static function updateNodeRecursive(array &$arr, callable $callback, array $options = [])
{
    $childrenKey = $options['childrenKey'] ?? "children";
    foreach ($arr as $k => $v) {
        call_user_func_array($callback, [&$v]);
        if (array_key_exists($childrenKey, $v) && $v[$childrenKey]) {
            $children = $v[$childrenKey];
            self::updateNodeRecursive($children, $callback, $options);
            $v[$childrenKey] = $children;
        }
        $arr[$k] = $v;
    }
}