2012-10-14 2 views
0

J'ai un tableau PHP bidimensionnel que j'ai besoin de transformer en arbre. La valeur 'path' dans chaque tableau interne est le chemin énuméré du noeud courant. (J'ai eu cette idée dans le livre de Bill Karwin sur SQL Antipatterns).Comment transformer cette structure de tableau PHP en arbre multidimensionnel?

Ainsi, le tableau que je commence à ressemble à ceci:

array(
[1] => array('name' => 'Animals', 'path' => '1/'), 
[2] => array('name' => 'Birds', 'path' => '1/3/'), 
[3] => array('name' => 'Cockatoos', 'path' => '1/3/5/'), 
[4] => array('name' => 'Fish', 'path' => '1/2/'), 
[5] => array('name' => 'Kookaburras', 'path' => '1/3/4/') 
) 

Comme vous avez pu le constater, l'indice de la matrice externe est dénuée de sens. J'ai simplement ordonné les tableaux internes par ordre alphabétique sur 'nom' et PHP a assigné des index numériques sur le tableau externe.

En ce qui concerne la valeur de 'chemin', le dernier segment de chaque chemin est un pseudo-identifiant pour le noeud, c'est-à-dire Animaux est le noeud 1, Birds est le noeud 3. Vous pouvez voir que route vers le noeud donné, par exemple 'Cockatoos' est parenté par 'Birds', qui est parenté par 'Animals'. Je veux garder l'ordre alphabétique des nœuds, mais les grouper par leur parent. En d'autres termes, je veux un tableau qui ressemble à ceci (dans l'ordre naturel):

[1]   => 'Animals' 
[1][3]  => 'Birds' 
[1][3][5] => 'Cockatoos' 
[1][3][4] => 'Kookaburras' 
[1][2]  => 'Fish' 

Je prévois itérer sur cette récursive pour imprimer une représentation visuelle de l'arbre. En essayant de passer d'un type de tableau à un autre, mes approches ont utilisé la récursivité, les variables variables et les expressions régulières, mais je continue à courir dans les rues.

De plus, existe-t-il une structure de données SPL ou un itérateur auquel je devrais penser?

Merci beaucoup!

EDIT: Désolé, aurait dû mentionner que la profondeur de l'arbre est variable. L'exemple ci-dessus a trois niveaux, mais en réalité il y en aura beaucoup plus.

Kim

Répondre

2

Cela fonctionne, peu importe la profondeur de l'arbre, possible en raison de l'utilisation de la fonction eval() (qui signifie évaluer). Mais le tri sur l'alphabet ne fonctionne pas encore correctement. Parce que les index des tableaux parents restent les mêmes, il est mélangé. BUt atleast vous pouvez déjà construire un arbre :)

<?php 
$a = array(
     array('name' => 'Animals', 'path' => '1/'), 
     array('name' => 'Birds', 'path' => '1/3/'), 
     array('name' => 'Eagles', 'path' => '1/3/3/'), 
     array('name' => 'Cockatoos', 'path' => '1/3/5/'), 
     array('name' => 'Fish', 'path' => '1/2/'), 
     array('name' => 'Kookaburras', 'path' => '1/3/4/') 
    ); 
Iterate($a); 
$tree = Iterate($a); 

var_dump($tree); 

OneLevelDeeper($tree); 
var_dump($tree); 

function Iterate($ChildArray) 
{ 
    $TreeArray; 
    foreach($ChildArray as $Key => $Value) 
    { 
     //echo $Key.': '.$Value['name']."\r\n"; 
     $exp = explode('/', $Value['path']); 
     $path; 
     foreach($exp as $int) 
     { 
      if($int != "") 
      { 
       $path[] = $int; 
      } 
     } 

     //Using Eval() function of PHP 
     $BuildSourceToEvaluate = '$TreeArray'; 
     for($i=0; $i<(count($path)-1); $i++) 
     { 
      $BuildSourceToEvaluate .= '[$path['.$i.']]'; 
     } 
     $BuildSourceToEvaluate .= '[] = $Value[\'name\'];'; 
     echo $BuildSourceToEvaluate."\r\n"; 
     Eval($BuildSourceToEvaluate); 
     //print_r($path); 
     /* 
     switch(count($path)) 
     { 
      case 0: 
      break; 
      case 1: 
       $TreeArray[] = $Value['name']; 
       //$TreeArray[$path[0]] = $Value['name']; //Use this for unique paths and keeping hold of the last ID in the tree path 
       //$TreeArray[$path[0]][] = $Value['name']; //Use this for non-unique tree paths 
      break; 
      case 2: 
       $TreeArray[$path[0]][] = $Value['name']; 
       //$TreeArray[$path[0]][$path[1]] = $Value['name']; //Use this for unique paths and keeping hold of the last ID in the tree path 
       //$TreeArray[$path[0]][$path[1]][] = $Value['name']; //Use this for non-unique tree paths 
      break; 
      case 3: 
       $TreeArray[$path[0]][$path[1]][] = $Value['name']; 
       //$TreeArray[$path[0]][$path[1]][$path[2]] = $Value['name']; //Use this for unique paths and keeping hold of the last ID in the tree path 
       //$TreeArray[$path[0]][$path[1]][$path[2]][] = $Value['name']; //Use this for non-unique tree paths 
      break; 
     } 
     */ 
     unset($path); 
    } 
    return $TreeArray; 
} 


function OneLevelDeeper(&$a) 
{ 
    sort($a); 
    foreach($a as $Key => $Value) 
    { 
     if(is_array($Value)) 
     { 
      sort($a[$Key]); 
      OneLevelDeeper($a[$Key]); 
     } 
    } 
} 

?> 
+0

Mike, merci d'avoir donné une fissure. S'il vous plaît voir la modification dans ma question initiale si. La profondeur de l'arbre est variable. Désolé, j'aurais dû le préciser dès le départ. Serait intéressé de voir comment vous résolvez le problème maintenant ... –

+0

@Kim - Ce n'est toujours pas un problème. Il y a probablement une profondeur maximale de l'arbre? Vous pouvez ajouter de nouveaux cas à la casse de la même manière pour ajouter de la profondeur supplémentaire à l'arbre. Sinon, vous devrez utiliser la fonction Eval() de PHP. –

Questions connexes