PHP - ссылки на дерево массивов, первое добавление в новый массив потеряно - PullRequest
0 голосов
/ 11 ноября 2010

У меня есть древовидная структура, состоящая из вложенных ассоциативных массивов. У меня есть набор путей, которые я хочу добавить в дерево, где каждый элемент в пути - это имя узла. Приведенный ниже код должен создать узел «2» под «a» (что он и делает) и создать узлы «i», «ii» и «iii» под «2». По какой-то причине первый узел, созданный в «2», теряется. Он напечатает, что он создается, но print_r показывает только «ii» и «iii».

$tree = array(
    name => 'root',
    children => array(
        array(
            name => 'a',
            children => array( ),
        ),
    ),
);


$paths = array(
    array('a','2','i'),
    array('a','2','ii'),
    array('a','2','iii'),
);


foreach ($paths as $path) {
    $node =& $tree;
    $found = true;
    while($found && count($path) > 0) {
        $name = $path[0];
        $found = false;
        echo "looking for $name\n";
        foreach ($node['children'] as &$child) {
            if($name == $child['name']) {
                echo "found $name\n";
                $node =& $child;
                $found = true;
                break;
            }
        }
        if($found) {
            array_shift($path);
        }
    }
    if(!$found) {
        echo "didn't find $name\n";
        while(count($path) > 0) {
            $name = array_shift($path);
            echo "creating $name in ".$node['name']."\n";
            $newNode = array(
                'name' => $name,
                'children' => array(),
            );
            $node['children'][] = $newNode;
            $node =& $newNode;
        }
    }
}

print_r($tree);

Я подозреваю, что проблема связана с тем, как я инициализирую дочерние элементы "2", так как он будет создан внутри цикла, но я не знаю, что делаю неправильно.

РЕДАКТИРОВАТЬ: Итак, я выяснил, как заставить это работать ... Изменение последнего внутреннего цикла с:

        $newNode = array(
            'name' => $name,
            'children' => array(),
        );
        $node['children'][] = $newNode;
        $node =& $newNode;

до

        $children =& $node['children'];
        $children[] = array(
            'name' => $name,
            'children' => array()
        );
        $node =& $children[count($children)-1];

, кажется, делает это, но я не уверен, почему. Должно быть хорошее объяснение.

1 Ответ

0 голосов
/ 11 ноября 2010

Все эти ссылки причиняют мне боль, однако есть одна очевидная ошибка, которую я вижу в:

$node['children'][] = $newNode;
$node =& $newNode;

Вторая строка заменяет $node ссылкой на $newNode, поэтому первая строкане используется.

В новой версии вы создаете массив $children, выполняете манипуляции, а затем задаете ссылку $node, поэтому он работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...