2010-09-23 7 views
3

J'ai un tableau comme celui-ci:tableau PHP récursion

Array ( 
[0] => Array ([id] => 1000 [enroller_id] => 1005) 

[1] => Array ([id] => 1005 [enroller_id] =>) 

[2] => Array ([id] => 1101 [enroller_id] => 1000) 

[3] => Array ([id] => 1111 [enroller_id] => 1000) 
) 

Je veux créer une matrice hiérarchie comme ceci:

Array(
[1005] => Array(
       [1000] => Array(
           [1101] => ... 
           [1111] => ... 
          ) 
       ) 
) 

Pouvez-vous me aider? Je pense que c'est une récursivité.

Répondre

3

Cela va faire ce que vous voulez, sauf qu'il ne met pas le premier élément (1005) dans le tableau:

function create_array($number, $data) 
{ 
    $result = array(); 
    foreach ($data as $row) 
    { 
     if ($row['enroller_id'] == $number) 
     { 
      $result[$row['id']] = create_array($row['id'], $data); 
     } 
    } 
    return $result; 
} 

print_r(create_array(1005, $data)); 

Sortie:

Array 
(
    [1000] => Array 
     (
      [1101] => Array() 
      [1111] => Array() 
     ) 
) 
+1

Merci. C'est la solution idéale! – pltvs

+0

Comment savons-nous par magie 1005? Et ne devrait-il pas être dans le résultat? – Wrikken

+0

1005 devrait être remplacé par null, et alors cela fonctionnerait. Et comme c'est souvent le cas, la récursivité est simple mais provoque des itérations excessives. – Matthew

3
//$paths is an array of references, in which _every_ item will sit at 'root' 
//level, but also as a reference as a child to it's parent. 

//initialize location of parentless/root items: 
$paths = array('N'=>array()); 

foreach($items as $item){ 
    //$target is the parent-id, or 'N' if we are a root node 
    $target = isset($item['enroller_id']) && !empty($item['enroller_id']) ? $item['enroller_id'] :'N'; 

    //if the parent is not yet in the paths array, make an entry for it 
    if(!isset($paths[$target]))  $paths[$target] = array(); 

    //if this item is not yet in the array (the previous statement could 
    //already have inserted it, make an array(
    if(!isset($paths[$item['id']])) $paths[$item['id']] = array(); 

    //add the current item as a reference to it's parent 
    $paths[$target][$item['id']] = &$paths[$item['id']]; 

    //Setting it as a reference has this consequence: 
    // when adding an item to the $paths[$id] array, it will 
    // automatically be added to $paths[$parent][$id], as 
    // both $paths[$id] & $paths[$parent][$id] point to the same 
    // location in memory. 
    // This goes to infinite depth: if $foo is a child of $id, and you 
    // add a node to it, it will be in 
    // $paths[$foo]    = array($child); 
    // $paths[$id][[$foo]   = array($child); 
    // $paths[$parent][$id][$foo] = array($child); 
    // 
    // Altering an item at any location in paths/the tree will alter it anywhere 
    // in the paths/tree, unsetting it anywhere only unset the data at that location, 
    // other locations will still have the same data (and the data will keep 
    // existing until the last reference is unset()) 

} 
//we are only interested in the 'root' nodes (all other nodes should be subnodes 
//in this tree 
$tree = $paths['N']; 
//remove all unused references in the $paths array 
//do remember to do this: cleaning up references is important 
unset($paths); 
//tree is now an array of 'normal' values (i.e. only 1 reference to each datapoint exists 
var_dump($tree); 

Ne pas oublier de unset chemins: les références peuvent vraiment vous mordre difficile de tracer des erreurs si vous ne prenez pas soin.

+2

Pouvez-vous expliquer comment cela fonctionne? – Sjoerd

+0

Il suffit de lier le nœud actuel et son nœud parent à chaque itération. Au début, vous avez juste deux nœuds orphelins. Finalement, ils se lient ensemble jusqu'à ce que vous ayez l'arbre final. Le seul effet secondaire est que les nœuds non localisés seront ignorés silencieusement, mais ce n'est pas vraiment une faute de l'algorithme. – Matthew

+0

Ce n'est pas une très bonne solution. – pltvs