Воссоздать массив из плоского (где дочерние массивы хранят индекс родительского массива) в многомерный? - PullRequest
2 голосов
/ 13 января 2010

Я пытаюсь взять плоский массив и воссоздать его так, чтобы он был многомерным. Я изучал array_combine и array_merge, но я не уверен, что любой из них даст мне то, на что я надеюсь ...

Массив в его текущей форме (и это просто упрощенный пример):

Array
(
    [0] => stdClass Object
        (
            [tid] => 31
            [name] => Safeway
            [parents] => Array
                (
                    [0] => 0
                )

        )

    [1] => stdClass Object
        (
            [tid] => 32
            [name] => Dairy
            [parents] => Array
                (
                    [0] => 31
                )

        )

    [2] => stdClass Object
        (
            [tid] => 33
            [name] => Milk
            [parents] => Array
                (
                    [0] => 32
                )

        )
)

Я пытаюсь создать многомерный массив, в котором каждый объект является подмассивом своего родителя. Итак, в приведенном выше примере я пытаюсь вывести:

Array
(
    [0] => stdClass Object
        (
            [tid] => 31
            [name] => Safeway
            [children] => Array
                (
                    [tid] => 32
                    [name] => Dairy
                    [children] => Array
                        (
                            [tid] => 33
                            [name] => Milk
                        )
                )

        )
)

Ответы [ 2 ]

1 голос
/ 13 января 2010

Во-первых, вы показываете не многомерный массив, а массив объектов StdClass.

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

// initiate result array
$multiArray = array();

// assume $items is your current array
foreach( $items as $item )
{
    // cast StdClass to array
    $objToArray = (array) $item;

    // if this item is initiated already merge it with the current item
    $multiArray[ $objToArray[ 'tid' ] ] = isset( $multiArray[ $objToArray[ 'tid' ] ] ) ? $multiArray[ $objToArray[ 'tid' ] ] + $objToArray : $objToArray;

    foreach( $objToArray[ 'parents' ] as $parentId )
    {
        // if parents don't exist yet, initiate them
        if( !isset( $multiArray[ $parentId ] ) )
        {
            $multiArray[ $parentId ] = array(
                'children' => array()
            );
        }

        // add this item to the parents children collection by reference (for efficiency)
        $multiArray[ $parentId ][ 'children' ][ $objToArray[ 'tid' ] ] = &$multiArray[ $objToArray[ 'tid' ] ];
    }
}

С этим вы можете легко найти предметы по id с помощью:

$item = $multiArray[ $someId ];

А чтобы завести ребенка:

$child = $item[ 'children' ][ $someChildId ];

Или все дети:

$children = $item[ 'children' ];

EDIT
Хорошо, я проверил это сейчас, и после добавления нескольких точек с запятой он работает нормально.

0 голосов
/ 13 января 2010

Хорошо, я делаю некоторые предположения здесь:

  • Каждый элемент имеет только 1 родителя, поэтому массив parents будет иметь только 1 tid
  • Массив отсортирован так, что дети появятся только после родителей
  • Elmenets верхнего уровня будет иметь родителя = 0

Учитывая это, попробуйте этот код:

$original = array ( ... your original array ... );
$nested = array ();

$n = count($original);
for ($i = 0; $i < $n; ++$i)
{
    $nested[$original[$i]->tid] = $original[$i];
    $nested[$original[$i]->tid]->children = array ();
}

while ($n-- && $current = $original[$n])
    if ($current->parents[0] != 0 && $current->parents[0] != $current->tid)
    {
        $nested[$current->parents[0]]->children[] = $current;
        unset ($nested[$current->tid]);
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...