开发者

PHP Reorder array to reflect parent / id hierarchy

How do I rearrange the following array

[0] => Array
    (
        [id] => 1
        [parent_id] => 0
        [name] => Accueil
    )

[1] => Array
    (
        [id] => 2
        [parent_id] => 0
        [name] => Exposants
    )

[2] => Array
    (
        [id] => 3
        [parent_id] => 0
        [name] => Visiteurs
    )

[3] => Array
    (
        [id] => 4
        [parent_id] => 0
        [name] => Medias
    )

[4] => Array
    (
        [id] => 5
        [parent_id] => 0
        [name] => Activités
    )

[5] => Array
    (
        [id] => 6
        [parent_id] => 1
        [name] => Contact
    )

[6] => Array
    (
        [id] => 7
        [parent_id] => 3
        [name] => Partenaires
    )

[7] => Array
    (
        [id] => 8
        [parent_id] => 2
        [name] => News
    )

So I come up with an array that reflects the hierarchy as shown by the id and parent_id fields? The array key is the ID field of array elements are parents. 开发者_开发知识库Inside this array is each time a child array that has its ID field as the key. Sample:

[1] => Array
        (
            [name] => Accueil
            [children] => array(
                [0] => bla,
                [3]     => bla2
            )
        )

    [2] => Array
        (
            [name] => Something
            [children] => array(
                [4] => bla3,
            )
        )


Works for any depth and allows children to precede parents:

<?php
$p = array(0 => array());
foreach($nodes as $n)
{
  $pid = $n['parent_id'];
  $id = $n['id'];

  if (!isset($p[$pid]))
    $p[$pid] = array('child' => array());

  if (isset($p[$id]))
    $child = &$p[$id]['child'];
  else
    $child = array();

  $p[$id] = $n;
  $p[$id]['child'] = &$child;
  unset($p[$id]['parent_id']);
  unset($child);

  $p[$pid]['child'][] = &$p[$id];    
}
$nodes = $p['0']['child'];
unset($p);
?>

Use var_dump on the $nodes result to see the structure. It is close to what you suggested. The major difference is that the keys are not the ids.


You could make this more DRY, but it's a quick and dirty way to handle it. Also, you could remove 6 lines if you could guarantee that each child record has a valid parent record and that the valid parent record precedes the child record in the original array.

$sorted = array();
foreach( $orig_ary as $item ) {
  if ( $item['parent_id'] === 0 ) {
    if ( !array_key_exists( $item['id'], $sorted ) ) {
      $sorted[ $item['id'] ] = array(
        'name' => '',
        'children' => array()
      );
    }
    $sorted[ $item['id'] ]['name'] = $item['name'];
  } else {
    if ( !array_key_exists( $item['parent_id'], $sorted ) ) {
      $sorted[ $item['parent_id'] ] = array(
        'name' => '',
        'children' => array()
      );
    }
    $sorted[ $item['parent_id'] ]['children'][ $item['id'] ] = $item['name'];
  }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜