2009-07-09 12 views
1

J'ai ce tableau:convertir un tableau 1D à tableau multidimensionnel en PHP

Array 
(
    [1] => animal 
    [1-1] => turtle 
    [1-1-1] => sea turtle 
    [1-1-2] => box turtle 
    [1-1-3] => green turtle 
    [1-1-3-1] => green turtle with brown tail 
) 

et je veux un peu comment convertir en:

Array 
(
    [1-title] => animal 
    [1-sons] => array(
      [1-1-title] => turtle 
      [1-1-sons] => array(
        [1-1-1] => sea turtle 
         [1-1-2] => box turtle 
        [1-1-3-title] => green turtle 
        [1-1-3-sons] => array(
          [1-1-3-title] => green turtle 
           ) 
        ) 
      ) 
) 

ou peut-être vous pouvez suggérer une meilleure façon pour organiser le tableau sorti ..

mais comment faire?

Je sais que ce n'est pas une tâche facile du tout, j'écris un analyseur qui marcheront sur des données et faire l'arbre d'eux ..

Merci d'avance pour votre aide et conseils ..

+0

Vous utilisez un tableau typé pour gérer les données tabulaires/hiérarchiques. J'ai une intuition il y aura plus (tortue, tatou, iquana), et que la récursivité peut continuer (avec des taches de rousseur, avec des champignons de la queue). Mais vous n'avez pas mentionné le stockage de base de données. Je me demande si vous avez envisagé d'utiliser XML? Avez-vous manipulé des données hiérarchiques en dehors de PHP? (Vous dites que vous savez que ce n'est pas facile, mais savez-vous vraiment comment "pas facile" c'est?!) – Smandoli

+0

Eh bien, la solution de mon cas sera ajouté à une classe plus grande qui est une sorte d'analyseur de texte, et j'ai besoin pour construire cet arbre à partir de texte écrit ici et là dans un grand champ de texte (d'une base de données) et l'utilisateur ne doit pas écrire ces choses 1-1-2 mais il est généré à partir d'une autre fonction qui lit le texte et le comprend alors donne ce tableau. donc il n'est pas possible d'envisager xml ici je pense .. –

Répondre

8

La meilleure façon d'organiser vos données seraient de telle manière:

array (
    'Animal' => 
    array (
    'Turtle' => 
    array (
     'Sea Turtle', 
     'Box Turtle', 
     'Green Turtle' => 
     array (
     'Green Turtle With Brown Tail', 
    ), 
     'Common Turtle', 
    ), 
), 
); 

// Or, otherwise written (equivalent to the above) 

$animals = array(); 
$animals['Animal'] = array(); 
$animals['Animal']['Turtle'] = array(); 
$animals['Animal']['Turtle'][] = 'Sea Turtle'; 
$animals['Animal']['Turtle'][] = 'Box Turtle'; 
$animals['Animal']['Turtle']['Green Turtle'] = array(); 
$animals['Animal']['Turtle']['Green Turtle'][] = 'Green Turtle With Brown Tail'; 
$animals['Animal']['Turtle'][] = 'Common Turtle'; 

Essentiellement, le nom de l'animal est la valeur, à moins qu'il a des enfants, la valeur est un tableau et la clé est le nom de l'animal.


De cette façon, vous pouvez facilement analyser les valeurs en procédant comme suit:

parse_animals($animals); 

function parse_animals($array, $indent = 0) { 
    if(!is_array($array)) return; // A little safe guard in case. 

    foreach($array as $key => $value) { 
    echo str_repeat(' ', $indent) . "- "; 

    if(is_array($value)) { 
     echo $key . "\n"; 
     parse_animals($value, $indent + 1); 
    } else { 
     echo $value . "\n"; 
    } 
    } 
} 

ci-dessus dans la console affichera les éléments suivants:

- Animal 
    - Turtle 
    - Sea Turtle 
    - Box Turtle 
    - Green Turtle 
     - Green Turtle With Brown Tail 
    - Common Turtle 

EDIT: Et voici une version qui le sortira pour une page Web.

function parse_animals_web($array) { 
    if(!is_array($array)) return; // A little safe guard in case. 

    foreach($array as $key => $value) { 
    echo '<ul>'; 

    if(is_array($value)) { 
     echo '<li>' . htmlentities($key) . "</li>"; 
     parse_animals_web($value); 
    } else { 
     echo '<li>' . htmlentities($value) . "</li>"; 
    } 

    echo '</ul>'; 
    } 
} 

La sortie est:

  • animaux
    • tortue
    • Sea Turtle
    • tortue de boîte
    • Green Turtle
      • tortue verte avec Brown Tail
    • Tortue commune

Peut-être que vous voulez obtenir les enfants d'un animal.

function get_children_of($array, $name) { 
    foreach($array as $key => $value) { 
    if(is_array($value)) { 
     if($key === $name) { 
     return $value; 
     } else { 
     return get_children_of($value, $name); 
     } 
    } 
    } 

    return array(); 
} 

Maintenant, nous pouvons obtenir tous les enfants du Green Turtle et les sorties.

$green_turtle = get_children_of($animals, 'Green Turtle'); 
parse_array($green_turtle); 

La sortie est:

- Green Turtle With Brown Tail 

EDIT: Puisque vous dites que vous êtes coincé avec le tableau d'entrée étant dans ce format bizarre, voici une fonction qui vous permet de convertir votre tableau dans le format que j'ai spécifié ci-dessus:

function convert_array($array) { 
    $new_array = array(); 

    $keys = array_keys($array); 
    foreach($keys as $key) { 
    $level = explode('-', $key); 
    $cur_level = &$new_array; 
    $cur_key = ''; 

    foreach($level as $o_key) { 
     $cur_key = ltrim($cur_key . '-' . $o_key, '-'); 
     $next_key = $cur_key . '-1'; 
     $value = $array[$cur_key]; 
     $has_child = array_key_exists($next_key, $array); 

     if($has_child) { 
     if(!array_key_exists($value, $cur_level)) { 
      $cur_level[$value] = array(); 
     } 
     $cur_level = &$cur_level[$value]; 
     } else { 
     $cur_level[] = $value; 
     } 
    } 
    } 

    return $new_array; 
} 
+0

oui ce sera la meilleure façon d'organiser mes données, j'ai trouvé que la fonction get_children_of est très utile. mais le parse_animals n'affiche pas les données comme vous l'avez dit, ou ça ne marche pas pour moi. Je ne peux pas envoyer un tableau qui ressemble à: Tableau ( [1] => animaux [1-1] => tortue [1-1-1] => tortue de mer [1-1-2] => tortue de boîte [1-1-3] => tortue verte [1-1-3-1] => tortue verte avec la queue marron ) alors je suis libre dans la façon dont c'est sorti, mais l'entrée ne peut pas être changé ... –

+1

J'ai ajouté une fonction pour convertir le tableau dans le format que j'ai spécifié ci-dessus. –

+0

Comme pour parse_animals, je l'ai conçu pour la sortie de la console (pas de page web, mais marcher dans le tableau est le même pour les deux). Si vous utilisez parse_animals sur une page Web, vous obtiendrez une seule ligne. Je vais ajouter une sortie de page Web. –

1

Cela dépend vraiment de comment/pour ce que vous allez utiliser l'arbre résultant. Pouvez-vous écrire plus de détails à ce sujet?

0

Essayez ceci:

$array = array(
    '1' => 'animal', 
    '1-1' => 'turtle', 
    '1-1-1' => 'sea turtle', 
    '1-1-2' => 'box turtle', 
    '1-1-3' => 'green turtle', 
    '1-1-3-1' => 'green turtle with brown tail' 
); 
$tree = array(); 
foreach ($array as $path => $val) { 
    $segments = explode('-', $path); 
    $last = array_pop($segments); 
    $tmp = &$tree; 
    $path = ''; 
    foreach ($segments as $segment) { 
     $path .= $segment.'-'; 
     if (!isset($tmp[$path.'sons'])) { 
      $tmp[$path.'sons'] = array(); 
     } 
     $tmp = &$tmp[$path.'sons']; 
    } 
    $tmp[$path.$last.'-title'] = $val; 
} 
print_r($tree); 

Mais votre structure de données n'a pas beaucoup de sens.

+0

cool, c'est exactement ce que je veux ..Merci beaucoup Gumbo –

+0

Je vous recommande comme les autres ici d'utiliser une structure de données différente, plus polyvalente que ce préfixe. – Gumbo

+0

alors que les 1-1-2 (les clés de tableau) ne sont pas réellement générées par des humains mais c'est juste une partie de tableau créée par un analyseur de texte donc je pense qu'il n'y aura pas de place pour des erreurs ou des conflits si c'est cette chose de préfixe .. –

0
$result = array(); 
foreach ($array as $position => $text) { 
    $p = explode('-', $position); 
    putIntoTree($result, $p, $text); 
} 

function putIntoTree(&$tree, $posInfo, $item) { 
    $index = array_shift($posInfo) - 1; 

    if (!count($posInfo)) { 
     $tree[$index]['name'] = $item; 
    } else {   
     if (!isset($tree[$index]['children'])) { 
      $tree[$index]['children'] = array(); 
     } 
     putIntoTree($tree[$index]['children'], $posInfo, $item); 
    } 
}  

Cela donne un moyen raisonnable de conserver les données.

Array 
(
    [0] => Array 
     (
      [name] => animal 
      [children] => Array 
       (
        [0] => Array 
         (
          [name] => turtle 
          [children] => Array 
           (
            [0] => Array 
             (
              [name] => sea turtle 
             ) 

            [1] => Array 
             (
              [name] => box turtle 
             ) 

            [2] => Array 
             (
              [name] => green turtle 
              [children] => Array 
               (
                [0] => Array 
                 (
                  [name] => green turtle with brown tail 
                 ) 
               ) 
             ) 
           ) 
         ) 
       ) 
     ) 
) 
+0

Merci Tom, en gardant les données dans une telle sortie est plus clair, je devrais gérer un moyen de combiner les sorties et les résultats et les fonctions que j'ai eu ici pour améliorer la classe –

0

Ce que vous essayez d'atteindre est une sorte d'un ensemble imbriqué et donc la meilleure façon de mettre en œuvre serait d'enregistrer l'identifiant parent dans l'entrée des enfants:

// the tree 
0 => array(parent => NULL, name => turtle), 
1 => array(parent => 0, name => green turtle), 
2 => array(parent => 0, name => blue turtle), 
3 => array(parent => 1, name => green turtle with yellow nose) 

Vous pouvez marcher à travers cette hiérarchie en utilisant une fonction récursive simple.

Si vous utilisez des objets au lieu de tableaux associatifs, vous obtenez même une augmentation des performances.

Questions connexes