Как получить предыдущее значение по ссылке в цикле foreach - PullRequest
0 голосов
/ 21 июня 2020

Я сократил свой реальный код, чтобы дать более точный пример. Вот что у меня есть:

$result = [];
$entry = null;
$prev = null;

$arr = [1, 2, 3];

foreach ($arr as $val) {
    $entry = [
        'val' => $val,
        'children' => []
    ];

    if ($prev) {
        array_push($prev['children'], $entry);
    } else {
        array_push($result, $entry);
    }

    $prev = $entry;
}

var_dump($result);

Когда этот код запускается, он выводит это:

array(1) {
  [0]=>
  array(2) {
    ["val"]=>
    int(1)
    ["children"]=>
    array(0) {
    }
  }
}

Мой желаемый результат:

array(1) {
  [0]=>
  array(2) {
    ["val"]=>
    int(1)
    ["children"]=>
    array(1) {
      [0]=>
      array(2) {
        ["val"]=>
        int(2)
        ["children"]=>
        array(1) {
          [0]=>
          array(2) {
            ["val"]=>
            int(3)
            ["children"]=>
            array(0) {
            }
          }
        }
      }
    }
  }
}

Я почти наверняка это происходит, потому что в этой строке:

$prev = $entry;

... значение $prev установлено на copy of $entry. Итак, на следующей итерации, когда я превращаю sh в $prev['children'], я изменяю скопированный массив, а не исходный, который был помещен в $result на первой итерации.

Я попытался использовать ссылку:

$prev = &$entry;

... но результат тот же. Теперь $prev устанавливается как содержимое $entry, но когда $entry установлен как новый массив на следующей итерации, $prev указывает на этот новый массив, а не на предыдущий, что бесполезно.

Я хочу, чтобы $prev указывал на содержимое из $entry и не изменялся при дальнейших мутациях переменной $entry. Как мне это сделать?

1 Ответ

0 голосов
/ 21 июня 2020

Проблема сводится к тому, на что указывают каждый раз. Вам необходимо использовать ссылки, чтобы позволить ему добавить новый элемент в правильную точку в текущей структуре, но ссылка будет отличаться в зависимости от того, в первый раз или нет.

В первый раз необходимо указать поле $result, так как именно здесь находится конечный результат, тогда оно будет обновлено относительно себя, так что запись отслеживает, где он находится ...

foreach ($arr as $val) {
    $entry = [
            'val' => $val,
            'children' => []
    ];
    
    if ($prev) {
        $prev['children'] = $entry;
        $prev = &$prev['children'];
    } else {
        $result = $entry;
        $prev = &$result;
    }
    
}
...