2015-05-15 21 views
6

Chciałbym zbudować tablicę wielowymiarową z tablicy. Na przykład chciałbymZbuduj wielowymiarową tablicę z tablicy w PHP

$test = array (
0 => 'Tree', 
1 => 'Trunk', 
2 => 'Branch', 
3 => 'Limb', 
4 => 'Apple', 
5 => 'Seed' 
); 

stać

$test = 
array (
    'Tree' => array (
     'Trunk' => array (
      'Branch' => array (
       'Limb' => array (
        'Apple' => array (
         'Seed' => array() 
        ) 
       ) 
      ) 
     ) 
    ) 
); 

lub prościej

$result[Tree][Trunk][Branch][Limb][Apple][Seed] = null; 

Próbuję to zrobić z funkcji rekurencyjnej, ale jestem uderzanie limit pamięci tak Wyraźnie robię to źle.

<?php 
$test = array (
0 => 'Tree', 
1 => 'Trunk', 
2 => 'Branch', 
3 => 'Limb', 
4 => 'Apple', 
5 => 'Seed' 
); 



print_r($test); 





print "results of function"; 

print_r(buildArray($test)); 



function buildArray (&$array, &$build = null) 
{ 
    if (count($array) > 0) 
    { 

     //create an array, pass the array to itself removing the first value 



     $temp = array_values($array); 
     unset ($temp[0]);   
     $build[$array[0]] = $temp; 


     buildArray($build,$temp); 



     return $build; 
    } 

    return $build; 


} 
+0

Jest to dobry przykład, dlaczego rekurencji niekoniecznie jest dobrym pomysłem, większość czasu.Zwykle bardzo łatwo jest oderwać rekursję, a dzięki temu uzyskujesz zazwyczaj szybszy, mniejszy ślad, łatwiejszy do zrozumienia kod. –

Odpowiedz

2

Ta funkcja działa rekurencyjnie i załatwia sprawę:

function buildArray($from, $to = []) { 
    if (empty($from)) { return null; } 
    $to[array_shift($from)] = buildArray($from, $to); 
    return $to; 
} 

W kodzie spodziewałbym widzisz błąd. Rozmawiasz z $build w swojej pierwszej iteracji, tak jakby to była tablica, podczas gdy domyślnie ustawiłeś ją na null.

8

Oto podejście z foreach i bez rekursji, który działa:

function buildArray($array) 
{ 
    $new = array(); 
    $current = &$new; 
    foreach($array as $key => $value) 
    { 
     $current[$value] = array(); 
     $current = &$current[$value]; 
    } 
    return $new; 
} 

[Demo]

teraz swoją funkcję ... Po pierwsze, używając $build[$array[0]] bez definiowania go jako tablica pierwszy produkuje E_NOTICE. Po drugie, twoja funkcja przechodzi w nieskończoną rekursję, ponieważ nie modyfikujesz się automatycznie $array ($temp to nie to samo), więc count($array) > 0 będzie prawdziwe przez całą wieczność.
Nawet jeśli modyfikowałeś $array, nie możesz już używać $array[0], ponieważ to wyzerujesz, a indeksy nie tylko się wysuwają. Do tego potrzebowałbyś array_shift.
Po tym, można przejść $build i $temp do swojej funkcji, co powoduje dodatkowo, ponieważ teraz przypisać $build do $temp, dlatego tworząc kolejną pętlę w swojej już nieskończenie-cyklicznego pętli.

Próbowałem naprawić wszystkie powyższe w swoim kodzie, ale w końcu zdałem sobie sprawę, że mój kod był teraz dokładnie tym z Pevara's answer, tylko z różnymi nazwami zmiennych, więc ... to jest to.

0

Używając wskaźnika, przesuń go jeszcze głębiej. Twoje dwa przykłady wyników dały array() i null dla najgłębszej wartości; to daje array() ale jeśli chcesz null wymienić $p[$value] = array(); z $p[$value] = $test ? array() : null;

$test = array(
    'Tree', 
    'Trunk', 
    'Branch', 
    'Limb', 
    'Apple', 
    'Seed' 
); 

$output = array(); 
$p = &$output; 
while ($test) { 
    $value = array_shift($test); 
    $p[$value] = array(); 
    $p = &$p[$value]; 
} 
print_r($output); 
2

Wydaje się być proste

$res = array(); 
$i = count($test); 
while ($i) 
    $res = array($test[--$i] => $res); 
var_export($res); 

cofnięcie

array ('Tree' => array ('Trunk' => array ('Branch' => array ('Limb' => array ('Apple' => array ('Seed' => array (),),),),),),) 
+0

Interesujące rozwiązanie, aby nie używać wskaźników. Ale nie najskuteczniejszy. –

+0

@JohnCartwright Dlaczego jest mniej wydajny niż funkcje wywołujące? – splash58

+0

Nie ma to nic wspólnego z funkcjami. Ma to związek z tworzeniem kopii i odniesień. –

Powiązane problemy