jareqpl
26.07.2012, 14:40:47
Witajcie, mam problem z napisaniem takiej funkcji która przeszłaby taką tablicę:
array(
'cos' => array( 'cos2' => 3, 'imie' => 'maciek' ),
'costam' => array('liczby' => array('pierwsza' => 1, 'druga' => 2), 'liczba2' => 3)
);
chcialbym zeby funkcja przyjęła tablice o dowolnej "głębokości" i wyswietlila cos takiego
array(
'cos.cos2' => 3,
'cos.imie' => 'maciek',
'costam.liczba.pierwsza' => 1,
'costam.liczba.druga' => '2',
'costam.liczba2' => 3
);
Oczywiście dane wymyślone teraz.
Próbowałem już różnych metod ale bardzo się w tym gubię.
Nie miałem do czynienia z rekurencją do tej pory. Mógłby ktoś pomóc?
jareqpl
26.07.2012, 14:59:41
dzięki wielkie, ja rozumiem jak działają funkcje ale z tym nie mogę sobie poradzić. Czytałem o funkcjach rekurencyjnych - proste umiem napisać. Ale to jest nieco bardziej złożone.
funkcja()
{
$nowa = null;
foreach()
if()
{
// sprawdzasz czy wartosc tablicy to array, jak tak dodajesz do zmiennej $nowa .= $key
// i wykonujesz funkcje jeszce raz, a jak nie leciesz dalej po tablicy
}
return $nowa;
}
Tak w skrócie.
jareqpl
26.07.2012, 15:41:21
Próbowałem takiego rozwiązania jak ty, wynik wygląda tak że cała tablica jest połączona kropkami.
$tab[cos.cos2.cos.imie.costam.liczba.pierwsza.costam.liczba.druga.costam.lic
zba2] itd...
Próbowałem już wielu rozwiązań, chyba z 3 godziny się z tym bawie. Nie wiem dlaczego ja tego nie mogę ogarnąć

Lag mózgu chyba.
shinuexx
26.07.2012, 19:00:52
function recursiveToSingle
($array,&$out = array(),$parentKey = ''){ $fun = __FUNCTION__;
foreach($array as $key => $val){
$fun($val,$out,$parentKey.$key.".");
else
$out[$parentKey.$key] = $val;
}
}
'cos2' => 3,
'imie' => 'maciek'
),
'pierwsza' => 1,
'druga' => 2
),
'liczba2' => 3
)
);
recursiveToSingle($t,$out);
print_vars($t,$out);
out:
Kod
array[2]
(
[cos] => array[2]
(
[cos2] => integer (3)
[imie] => string[6] ("maciek")
)
[costam] => array[2]
(
[liczby] => array[2]
(
[pierwsza] => integer (1)
[druga] => integer (2)
)
[liczba2] => integer (3)
)
)
array[5]
(
[cos.cos2] => integer (3)
[cos.imie] => string[6] ("maciek")
[costam.liczby.pierwsza] => integer (1)
[costam.liczby.druga] => integer (2)
[costam.liczba2] => integer (3)
)
nie tylko rekurencja ale i referencja jest tu potrzebna ponieważ tablica ma się zwiększać nawet w podtablicach.
lukaskolista
27.07.2012, 08:10:07
Referencja wcale nie jest potrzebna. Twoj kod przerobiony tak, aby referencji nie uzywac:
function recursiveToSingle
($array, $out = array(), $parentKey = '') {
$fun = __FUNCTION__;
foreach($array as $key => $val)
{
{
$out += $fun($val,$out,$parentKey.$key.".");
}
else
{
$out += array($parentKey.$key => $val); }
}
return $out;
}
'cos2' => 3,
'imie' => 'maciek'
),
'pierwsza' => 1,
'druga' => 2
),
'liczba2' => 3
)
);
$out = recursiveToSingle($t);
IMO im mniej referencji (poza obiektowoscia), tym lepiej.
PS.
cos formatowanie kodu dziwnie dziala, kod nie wyglada tak, jak w oryginale, ale trudno.
Shido
27.07.2012, 08:30:28
Cytat(shinuexx @ 26.07.2012, 20:00:52 )

Kod
array[2]
(
[cos] => array[2]
(
[cos2] => integer (3)
[imie] => string[6] ("maciek")
)
[costam] => array[2]
(
[liczby] => array[2]
(
[pierwsza] => integer (1)
[druga] => integer (2)
)
[liczba2] => integer (3)
)
)
array[5]
(
[cos.cos2] => integer (3)
[cos.imie] => string[6] ("maciek")
[costam.liczby.pierwsza] => integer (1)
[costam.liczby.druga] => integer (2)
[costam.liczba2] => integer (3)
)
Taki efekt, bądź podobny, daje przecież:
lukaskolista
27.07.2012, 08:52:24
Shido:
niestety nie, tutaj chodzi o konwersje tablicy wielowymiarowej do jednowymiarowej laczac klucze kropka.
Shido
27.07.2012, 08:57:38
A dobra, mój błąd nie doczytałem...
Cytat
cos formatowanie kodu dziwnie dziala, kod nie wyglada tak, jak w oryginale, ale trudno.
Działa dobrze, tylko w swoim edytorze masz tabulacje zamiast spacji i jak zawsze w takich wypadkach robi się burdel
shinuexx
27.07.2012, 09:20:18
lukaskolista:
w sumie zapomniałem że można użyć '+';P
Swoją drogą to przydatny kod.
lukaskolista
27.07.2012, 09:26:38
Do czego sie przyda? Jak dla mnie jest kompletnie bezuzyteczny, poniewaz w kluczach tablic asocjacyjnych mozna uzywac kropki, a wtedy cala struktura tablicy zostanie zaburzona.
rocktech.pl
27.07.2012, 09:36:20
Witam.
Poc kombinować SPL i
RecursiveArrayIterator 'cos' => array('cos2' => 3, 'imie' => 'maciek'), 'costam' => array('liczby' => array('pierwsza' => 1, 'druga' => 2), 'liczba2' => 3
) );
$iterator = new RecursiveArrayIterator ( $myArray );
...
lukaskolista
27.07.2012, 09:40:08
My nie kombinujemy, podczas iteracji tablicy przez iterator trzeba wykonac dokladnie te same operacje, ktore wykonywane sa w ciele funckji rekurencyjnej. W tym temacie nie chodzi o to, aby rekursywnie iterowac tablice, tylko zeby z tablicy wielowymiarowej zrobic jednowymiarowa.
jareqpl
27.07.2012, 09:42:57
Dziękuje wam bardzo. Nie wiem dlaczego nie mogłem tego zrobić, to był pierwszy problem z którym się tak długo borykałem od kąd programuje. Jeszcze raz dziękuje i pozdrawiam.
erix
27.07.2012, 09:46:55
~lukaskolista, owszem, to jest kombinowanie, bo stwarzacie koło na nowo.
Iteratory albo
array_walk_recursive, to najlepsze rozwiązanie tego problemu.
lukaskolista
27.07.2012, 10:14:33
Nie rozumiesz jednej rzeczy: my nie narzucamy rozwiazan, tylko przedstawiamy sposob. Kazdy sobie zrobi jak chce. Ty uwazasz, ze powinno byc inaczej, ktos inny uwaza ze jest ok, a znajdzie sie na pewno osoba, ktora by to jeszcze inaczej zrobila. W jezykach programowania jedna rzecz da sie zrobic na wiele konkurencyjnych sposobow. Wybor odpowiedniego zalezy od konkretnego programisty.
erix
27.07.2012, 10:22:42
Cytat
W jezykach programowania jedna rzecz da sie zrobic na wiele konkurencyjnych sposobow. Wybor odpowiedniego zalezy od konkretnego programisty.
A złożoność obliczeniowa, to została w podręcznikach?
lukaskolista
27.07.2012, 11:29:32
Wiec prosze, policz mi zlozonosc, przedstaw wyniki dla tych 2 rozwiazan i bedziemy dyskutowac dalej.
erix
27.07.2012, 11:33:28
Do tego nie trzeba liczyć - wystarczy benchmark na każde z rozwiązań.
A podejrzewam na 90%, że funkcje wbudowane będą szybsze od ręcznej implementacji przez rekurencję.
lukaskolista
27.07.2012, 12:00:09
A ja nie podejrzewam, jak przedstawisz konkretne wyniki to przyznam Ci racje. Nie lubie gdybania.
erix
27.07.2012, 12:01:31
To sprawdź. [;
Ja teraz na to czasu nie mam.
lukaskolista
27.07.2012, 12:11:06
Ale to Ty mi zarzucasz bezsensownosc kodu i jego duza zlozonosc, wiec to Ty powinienes to udowodnic - ja tez nie mam czasu.
Skoro nie chcesz udowodnic, to ja to juz zrobie:
lukaskolista: 1.962198972702s
roctech + erix (RecursiveArrayIterator): 5.3361186981201s
Wyniki podane w sekundach dla 100 000 wykonan. Nie bede juz nawet sprawdzal ilosci zuzytej pamieci operacyjnej, bo obiekty iteratora waza swoje, a funkcja rekurencyjna nie.
Wiec nastepnym razem sprawdz, czy masz racje zanim uznasz, ze ja masz.
jareqpl
29.07.2012, 12:59:36
Ale ja wiem że można było użyć array_walk_recursive tylko że miałem duży problem z napisaniem tej funkcji i chciałem się dowiedzieć jak to zrobić żeby się czegoś więcej nauczyć. Dlatego poprosiłem o wyjaśnienie. Pozdrawiam
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę
kliknij tutaj.