PHP Traversing Function для преобразования одного массива во вложенный массив с дочерними элементами - на основе родительского идентификатора - PullRequest
3 голосов
/ 19 января 2010

У меня есть массив, похожий на этот:

Array
(
    Array
    (
        [ID] => 1
        [parentcat_ID] => 0
    ),
    Array
    (
        [ID] => 2
        [parentcat_ID] => 0
    ),
    Array
    (
        [ID] => 6
        [parentcat_ID] => 1
    ),
    Array
    (
        [ID] => 7
        [parentcat_ID] => 1
    ),
    Array
    (
        [ID] => 8
        [parentcat_ID] => 6
    ),
    Array
    (
        [ID] => 9
        [parentcat_ID] => 1
    ),
    Array
    (
        [ID] => 13
        [parentcat_ID] => 7
    ),
    Array
    (
        [ID] => 14
        [parentcat_ID] => 8
    )

)

Но мне нужна функция, чтобы рекурсивно поместить каждый элемент в массив 'children' внутри соответствующего родительского массива. Так это будет выглядеть примерно так:

Array
(
    Array
    (
        [ID] => 1
        [parentcat_ID] => 0
        [children] => Array (
            Array
            (
                [ID] => 6
                [parentcat_ID] => 1
                [childen] => Array (
                    Array
                    (
                        [ID] => 8
                        [parentcat_ID] => 6
                        [children] => Array (
                             Array
                             (
                                 [ID] => 14
                                 [parentcat_ID] => 8
                             )
                        )
                    )
                )
            ),
            Array
            (
                [ID] => 7
                [parentcat_ID] => 1
                [children] => Array(
                     Array
                     (
                         [ID] => 13
                         [parentcat_ID] => 7
                     )
                ) 
            ),
            Array
            (
                [ID] => 9
                [parentcat_ID] => 1
            )

        )
    )
    Array
    (
        [ID] => 2
        [parentcat_ID] => 0

    )

)

Надеюсь, это имеет смысл!

Ответы [ 2 ]

12 голосов
/ 19 января 2010

Попробуйте (протестировано в php 5.2):

$inArray = array(
    array('ID' => '1', 'parentcat_ID' => '0'),
    array('ID' => '2', 'parentcat_ID' => '0'),
    array('ID' => '6', 'parentcat_ID' => '1'),  
    array('ID' => '7', 'parentcat_ID' => '1'),
    array('ID' => '8', 'parentcat_ID' => '6'),          
    array('ID' => '9', 'parentcat_ID' => '1'),  
    array('ID' => '13', 'parentcat_ID' => '7'),
    array('ID' => '14', 'parentcat_ID' => '8'),     
);

function makeParentChildRelations(&$inArray, &$outArray, $currentParentId = 0) {
    if(!is_array($inArray)) {
        return;
    }

    if(!is_array($outArray)) {
        return;
    }

    foreach($inArray as $key => $tuple) {
        if($tuple['parentcat_ID'] == $currentParentId) {
            $tuple['children'] = array();
            makeParentChildRelations($inArray, $tuple['children'], $tuple['ID']);
            $outArray[] = $tuple;   
        }
    }
}

$outArray = array();
makeParentChildRelations($inArray, $outArray);

print_r($outArray);
3 голосов
/ 19 января 2010

Я недавно ответил на аналогичный вопрос. Здесь это так. Надеюсь, что это соответствует вашим потребностям. Если нет, дайте мне знать, и я приспособлю его к вашим спецификациям.

EDIT
Хорошо, вот настроенная версия, которая должна соответствовать вашим потребностям.

function generateMultiArray( array $flatArray )
{

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

    // iterate $flatArray
    foreach( $flatArray as $item )
    {
        // for convenience, initiate these vars
        $id = $item[ 'ID' ];
        $parentId = $item[ 'parentcat_ID' ];

        // initiate this item's children array;
        $item[ 'children' ] = array();

        // if parent doesn't exist yet, initiate it along with an empty 'children' array
        if( !isset( $multiArray[ $parentId ] ) )
        {
            $multiArray[ $parentId ] = array(
                'children' => array()
            );
        }

        // if this item is initiated already (as being a parent) merge it with the current item
        $multiArray[ $id ] = isset( $multiArray[ $id ] ) ? $multiArray[ $id ] + $item : $item;

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

    }

    return $multiArray;
}

Помните, что эта функция также делает все элементы доступными в качестве корневого элемента массива результатов с их идентификатором в качестве индекса.

Итак, чтобы получить доступ к дочерним элементам с произвольным идентификатором n, вы должны сделать:

$multiArray = generateMultiArray( $yourFlatArray );
$children = $multiArray[ n ][ 'children' ]; // replace n with the id

РЕДАКТИРОВАТЬ 2
Забыл ввести дочерний массив для элементов, которые не являются родительскими; добавлено сейчас. В противном случае это приведет к уведомлению при попытке получить к нему доступ:

$multiArray = generateMultiArray( $yourFlatArray );
$children = $multiArray[ $someIdWithoutChildren ][ 'children' ];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...