Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Jak segregować wielowymiarowe tablice?
Forum PHP.pl > Forum > PHP
MESSIAH :)
Chciałbym się dowiedzieć jak można posortować wielowymiarowe tablice mam na myśli kilku wymiarowe a nie dwie. Z tego co się orientuje to muszę każdy wymiar schować do nowo utworzonej tablicy i wtedy sortować i tak z każdym wymiarem?
Powiedzmy że tablica wygląda tak:
Kod
Array
(
    [0] => .htaccess.
    [1] => .htpasswd
    [2] => hhgute.hhi
    [3] => autoload.php
    [4] => config.php
    [5] => fp.map
    [6] => index.php
    [7] => test.php
    [8] => Array
        (
            [0] => .pemhtaccess
        )

    [9] => Array
        (
            [con] => Array
                (
                    [ror] => Array
                        (
                            [0] => Roctor.php
                            [1] => Roe.php
                            [2] => Derator.php
                            [Dtor] => Array
                                (
                                    [0] => Mared.php
                                    [1] => Chased.php
                                    [2] => Gred.php
                                    [3] => Groed.php
                                    [4] => Restract.php
                                )

                            [Dis] => Array
                                (
                                    [0] => Marked.php
                                    [1] => Chased.php
                                    [2] => Grouped.php
                                    [3] => Grouped.php
                                    [4] => Regt.php
                                )

                            [3] => Badion.php
                            [4] => Rouser.php
                            [5] => fns.php
                            [6] => bootstrap.php
                            [Ror] => Array
                                (
                                    [0] => S.php
                                )

                            [7] => Dispr.php
                        )

                )

            [view] => Array
                (
                    [0] => viewLr.php
                    [1] => view.php
                    [2] => wid.php
                )

        )
Pyton_000
A Ty dalej swoje...
http://php.net/manual/en/function.array-multisort.php
MESSIAH :)
Witam serdecznie. Lepiej mi pomóż się z tym uporać. Jak mam posortować ten burdel? Masz jakieś pomysły?
Crozin
1. Jak miałoby to być posortowane?
2. Dostałeś na tacy podaną funkcję, która najprawdopodobniej rozwiązuje Twój problem, więc może spróbuj z niej skorzystać...
Pyton_000
A jeszcze lepiej posortować PRZED budowaniem takiej durnej tablicy... Ani ona przydatna, ani poręczna... tfu... zapomniałem... innowacyjny autoloader biggrin.gif
MESSIAH :)
Niestety array_multisort() wywala mi błąd:
Fatal error: Uncaught exception 'ErrorException' with message 'Array to string conversion'
kiedy użyje array_multisort($r, SORT_ASC, SORT_STRING);


http://stackoverflow.com/questions/1790493...-while-installi

Niestety jest to serwer na którym nie jestem adminem i nie mogę nic zmieniać.

Posortować ale jak kiedy mam różne klucze id oraz stringi.
Pyton_000
Od rzyci strony się do tego zabierasz...
MESSIAH :)
Masz proszę oto funkcja:
Kod
$ritit = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(__DIR__, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST);
$r = array();
foreach ($ritit as $splFileInfo) {
    $path = $splFileInfo->isDir()
        ? array($splFileInfo->getFilename() => array())
        : array($splFileInfo->getFilename());

    for ($depth = $ritit->getDepth() - 1; $depth >= 0; $depth--) {
        $path = array($ritit->getSubIterator($depth)->current()->getFilename() => $path);
    }

    $r = array_merge_recursive($r, $path);

}

No proszę to ugryźć samemu. Tablica może wygląda jak wygląda ale to dzięki funkcji array_merge_recursive($r, $path);
kapslokk
Stwórz sobie tablicę w formie:
  1. 0 => '.',
  2. 1 => 'jakis_plik.php',
  3. 2 => 'jakis_folder/jakis_plik2.php'
  4. ...
  5. )


Posortuj sobie to, a pozniej z tak posortowanej tablicy stworz tablice wielowymiarowa.
MESSIAH :)
Stworzyłem takową lecz jest nie posortowana bo serwer chyba sortuje według czasu ostatniej modyfikacji. Więc nie jest posortowana według folderów.
kapslokk
To sobie napisz sortowanie bąbelkowe na szybko. Serio nie potrafisz posortować alfabetycznie tablicy?
MESSIAH :)
No niestety nie umie bo się dopiero uczę.
Tomplus
Pobierz sobie klasę: http://www.phpclasses.org/package/2056-PHP...dimensions.html

Powinna rozwiązać twoje problemy.
MESSIAH :)
Cytat(Tomplus @ 10.10.2015, 22:50:58 ) *
Pobierz sobie klasę: http://www.phpclasses.org/package/2056-PHP...dimensions.html

Powinna rozwiązać twoje problemy.

Niestety to sortowanie jest sztywne czyli sortuje po stałych elementach tablicy a w moim przypadku jest to wartość zmienna.

Cytat(Pyton_000 @ 10.10.2015, 22:55:24 ) *

Niestety ale to sortuje według daty bo tak najprościej.

Udało mi się posortować w części alfabetycznie ale tylko w części bo funkcja jakoś nie chce tego łyknąć. Nie mam pojęcia dlaczego część tabeli została posegregowana. Segregacja ta nie rozpoznaje koniec folderu gdzie powinna posegregować i dopiero przejść do następnego subfolderu.
Crozin
1. Nadal nie podałeś nam jak finalnie ma być posortowana ta tablica...
2. Po co w ogóle korzystasz z RecursiveIteratorIterator skoro chwilę później (wewnątrz pętli) de facto niwelujesz jego działanie odtwarzając zagnieżdżoną strukturę katalogów? Skorzystanie z "gołego" RecursiveDirectoryIteratora byłoby dużo wygodniejsze.
3. Dlaczego raz w kluczach przechowujesz nazwę katalogu, raz nie przechowujesz nic (indeks numeryczny)?
4. Zdajesz sobie sprawę, że przypisywanie czegokolwiek do $path w przypadku czegoś co nie jest katalogiem mija się z celem, bo później zawsze to nadpisujesz w pętli for?
5. Rozumiesz w ogóle co robi Twój kod i za co odpowiedzialne są jego poszczególne elementy?
MESSIAH :)
Chcę to posortować tak jak system Windows: Według nazw plików oraz nazw katalogów.
Sorki za przykład ale pochodzą one z SOF, widocznie siedzą tam same nieuki. Aktualnie mam inny kod który rozbija na katalogi i na katalogi z plikami. Teraz pewnie wystarczy sprawdzać katalogi czy są puste i je sortować.
Crozin
Cytat
Chcę to posortować tak jak system Windows: Według nazw plików oraz nazw katalogów.
System Windows nie sortuje pilów. Nie robi tego również system plików (NTFS). Realizowane jest to dopiero przez program Explorer, a i ten domyślnie robi to inaczej niż podałeś. Wracając do tematu... wykorzystując RecursiveDirectoryIteratora sortuj elementy każdego katalogu z osobna (w ramach osobnej, lokalnej tablicy/kolekcji). Na końcu dostaniesz w efekcie wszystkie elementy posortowane wg tego samego wzoru.
MESSIAH :)
Udaje mi się posortować lecz ostatni problem tkwi w dużych literach. Mam pliki których nazwy zaczynają się z dużych liter i teraz sprawa wygląda tak że Duże litery są posortowane najpierw a dopiero później małe. Jak to rozwiązać? Znalazłem zastosowanie: natcasesort(). Pytanie teraz jak sprawdzić dany katalog czy zawiera pliki?

Cytat(Crozin @ 11.10.2015, 17:22:17 ) *
System Windows nie sortuje pilów. Nie robi tego również system plików (NTFS). Realizowane jest to dopiero przez program Explorer, a i ten domyślnie robi to inaczej niż podałeś.

Wydaje mi się iż nie masz racji. Dawniej był DOS i to on sortował pliki natomiast Windows jest graficzną nakładką DOSa i korzysta z jego zasobów a dopiero programy takie jak explorer korzystają np z funkcji sortowania.
https://en.wikipedia.org/wiki/List_of_DOS_commands
Crozin
Cytat
Udaje mi się posortować lecz ostatni problem tkwi w dużych literach. Mam pliki których nazwy zaczynają się z dużych liter i teraz sprawa wygląda tak że Duże litery są posortowane najpierw a dopiero później małe. Jak to rozwiązać?
Do porównywania użyj jakiejś funkcji ignorującej wielkość znaków, np. strcasecmp
Cytat
Pytanie teraz jak sprawdzić dany katalog czy zawiera pliki?
Rzuć okiem na dokumentację RecursiveDirectoryIteratora.
Cytat
Cytat
System Windows nie sortuje pilów. Nie robi tego również system plików (NTFS). Realizowane jest to dopiero przez program Explorer, a i ten domyślnie robi to inaczej niż podałeś.
Wydaje mi się iż nie masz racji. Dawniej był DOS i to on sortował pliki natomiast Windows jest graficzną nakładką DOSa i korzysta z jego zasobów a dopiero programy takie jak explorer korzystają np z funkcji sortowania.
Pomijając fakt, że Windows od dawien dawna nie ma z DOS-em nic wspólnego, to przecież to jest dokładnie to co napisałem...
MESSIAH :)
Teraz mam taką tablicę:

  1. [13] => ./core/con/ro/functions.php
  2. [14] => ./core/con/ro/bootstrap.php
  3. [15] => ./core/con/ro/RouPar/Std.php
  4. [16] => ./core/con/ro/RouParer.php
  5. [17] => ./core/con/ro/RouCollector.php
  6. [18] => ./core/con/ro/Route.php
  7. [19] => ./core/con/ro/Disher/Rtract.php
  8. [20] => ./core/con/ro/Disher/Maed.php
  9. [21] => ./core/con/ro/Disher/Gsed.php
  10. [22] => ./core/con/ro/Disher/GtBased.php
  11. [23] => ./core/con/ro/Disher/Chsed.php
  12. [24] => ./core/con/ro/Disher.php
  13. [25] => ./core/con/ro/Datator/Rebstract.php
  14. [26] => ./core/con/ro/Datator/Mased.php
  15. [27] => ./core/con/ro/Datator/Grouased.php
  16. [28] => ./core/con/ro/Datator/Groased.php
  17. [29] => ./core/con/ro/Daed.php
  18. [30] => ./core/con/ro/Dor.php
  19. [31] => ./core/con/ro/Bion.php

Ale niestety jest niemożliwe posortowanie według podkatalogów. Szukałem w całym necie i nigdzie nic nie ma. PHP jest ułomnym językiem skoro nie ma zdefiniowanego sortowania domyślnie według nazw. Problem z tą tablicą polega na tym iż PHP nie potrafi rozróżnić nazwy pliku od nazwy katalogu i żadna funkcja sortowania nie daje efektu. Wątpię by ktoś tutaj znał rozwiązanie. Nawet na SOF mają z tym problem. Używając funkcji natcasesort() na tej tablicy powinno odnieść skutek lecz efekt jest taki:
  1. [31] => ./core/con/ro/Bion.php
  2. [14] => ./core/con/ro/bootstrap.php
  3. [29] => ./core/con/ro/Daed.php
  4. [28] => ./core/con/ro/Datator/Groased.php
  5. [27] => ./core/con/ro/Datator/Grouased.php
  6. [26] => ./core/con/ro/Datator/Mased.php
  7. [25] => ./core/con/ro/Datator/Rebstract.php
  8. [24] => ./core/con/ro/Disher.php
  9. [23] => ./core/con/ro/Disher/Chsed.php
  10. [21] => ./core/con/ro/Disher/Gsed.php
  11. [22] => ./core/con/ro/Disher/GtBased.php
  12. [20] => ./core/con/ro/Disher/Maed.php
  13. [19] => ./core/con/ro/Disher/Rtract.php
  14. [30] => ./core/con/ro/Dor.php
  15. [13] => ./core/con/ro/functions.php
  16. [17] => ./core/con/ro/RouCollector.php
  17. [15] => ./core/con/ro/RouPar/Std.php
  18. [16] => ./core/con/ro/RouParer.php
  19. [18] => ./core/con/ro/Route.php

Jak widzimy system nie może rozróznić dwóch różnych stringów:
[29] => ./core/con/ro/Daed.php
[28] => ./core/con/ro/Datator/Groased.php

Nie ma się do tego jak zabrać aby to rozwalić.
redeemer
Co to za bełkot (np. "Jak widzimy system nie może rozróznić dwóch różnych stringów" - przecież widać dokładnie coś odwrotnego). Nie potrafisz się wysłowić i ja w sumie dalej do końca nie wiem o co chodzi bo zamiast dać przykłady "jak jest teraz", a "czego oczekujesz" to nabijasz posty jakimiś bzdurami (z tego co pamiętam, to ostatni wątek z tym "niemożliwym w PHP" sortowaniem został nawet zamknięty)
Cytat
Ale niestety jest niemożliwe posortowanie według podkatalogów. Szukałem w całym necie i nigdzie nic nie ma. PHP jest ułomnym językiem skoro nie ma zdefiniowanego sortowania domyślnie według nazw. Problem z tą tablicą polega na tym iż PHP nie potrafi rozróżnić nazwy pliku od nazwy katalogu i żadna funkcja sortowania nie daje efektu. Wątpię by ktoś tutaj znał rozwiązanie. Nawet na SOF mają z tym problem.
Jest możliwe. Źle szukałeś. Dalej nie rozumiesz, że to nie PHP jest za to odpowiedzialny. Problem polega z Tobą, bo myślisz że pozjadałeś wszystkie rozumy, a jak czegoś nie potrafisz to "się nie da", albo "PHP jest do dupy" (to nie pierwszy wątek gdzie można to zaobserwować). Z takim podejściem nie wróżę Ci wielkiej kariery w zawodzie programisty, chyba że będziesz miał ksywę "nie da się" :-)

Wracając do problemu, jeśli dobrze zrozumiałem, to nawet mając Twoją tablicę wynikową można to łatwo zrobić:
  1. <?php
  2.  
  3. $t = [
  4. './core/con/ro/Daed.php',
  5. './core/con/ro/Datator/Groased.php',
  6. './core/con/ro/Datator/Grouased.php',
  7. './core/con/ro/Datator/Mased.php',
  8. './core/con/ro/Datator/Rebstract.php',
  9. './core/con/ro/Disher.php',
  10. './core/con/ro/Disher/Chsed.php',
  11. './core/con/ro/Disher/Gsed.php',
  12. './core/con/ro/Disher/GtBased.php',
  13. './core/con/ro/Disher/Maed.php',
  14. './core/con/ro/Disher/Rtract.php',
  15. './core/con/ro/Dor.php'
  16. ];
  17.  
  18. $n = [];
  19.  
  20. foreach($t as $k => $v) {
  21. $n[] = ['path'=>$v, 'level'=>substr_count($v, '/')];
  22. }
  23.  
  24. $sort = [];
  25. foreach($n as $k=>$v) {
  26. $sort['path'][$k] = $v['path'];
  27. $sort['level'][$k] = $v['level'];
  28. }
  29.  
  30. array_multisort($sort['level'], SORT_ASC, $sort['path'], SORT_ASC, $n);
  31.  
  32.  
  33. foreach($n as $v) {
  34. echo $v['path'].PHP_EOL;
  35. }

Wynik:
Kod
./core/con/ro/Daed.php
./core/con/ro/Disher.php
./core/con/ro/Dor.php
./core/con/ro/Datator/Groased.php
./core/con/ro/Datator/Grouased.php
./core/con/ro/Datator/Mased.php
./core/con/ro/Datator/Rebstract.php
./core/con/ro/Disher/Chsed.php
./core/con/ro/Disher/Gsed.php
./core/con/ro/Disher/GtBased.php
./core/con/ro/Disher/Maed.php
./core/con/ro/Disher/Rtract.php
Czy takiego wyniku oczekujesz?

Ps. Ile w ogóle znasz języków, żeby wypowiadać się na temat ułomności PHP?
MESSIAH :)
Dzięki za nakierowanie na właściwy trop. Problem jednak jest u minie z sortowaniem dużych i małych liter. Mianowicie Większe litery są przed małymi. Użyłem:
  1. $n[] = ['path'=>strtolower($v), 'level'=>substr_count($v, '/')];

Teraz sortuje dobrze lecz jak można po zmniejszeniu tych stringów przywrócić je do poprzedniej formy?
redeemer
  1. $n[] = ['path'=>strtolower($v), 'level'=>substr_count($v, '/'), 'org_path'=>$v];
org_path będzie zawierał oryginalną ścieżkę

Edit: Albo sprawdź:
  1. array_multisort($sort['level'], SORT_ASC, SORT_STRING | SORT_FLAG_CASE, $sort['path'], SORT_ASC, SORT_STRING | SORT_FLAG_CASE, $n);

MESSIAH :)
Wielkie dzięx kolego. Ten drugi multisort zrobił robotę. Teraz będę musiał na spokojnie przeanalizować cały kod. Jest jeszcze mały problem z sortowaniem mniejszych wartości a mianowicie tak to wygląda:
/.htaccess.
/.htpasswd
/autoload.php
/config.php
/Foute.hhi
/files_map.map
/index.php
/te.php
/tes.php
/test.php
/test1.php
/testy.php
/.protect/.pemhtaccess
/views/hello.php
/views/uzwnik.html
/core/view/view.php
/core/view/viewLoader.php
/core/view/wok.php
/views/css/unik.css
redeemer
Zobacz to. Pisane na kolanie, nie sprawdzałem czy działa:
  1.  
  2. function mysort($dir, &$out) {
  3. $t = [];
  4. $dirs = [];
  5.  
  6. $files = array_diff(scandir($dir), ['..', '.']);
  7.  
  8. foreach($files as $file) {
  9. $path = $dir.'/'.$file;
  10. if (is_dir($path)) {
  11. $dirs[] = $path;
  12. } else {
  13. $t[] = $path;
  14. $out[] = $path;
  15. }
  16. }
  17.  
  18. foreach($dirs as $d) {
  19. $t[] = mysort($d, $out);
  20. }
  21.  
  22. return $t;
  23. }
  24.  
  25. $out = [];
  26. mysort('/tmp/test', $out);
  27. var_dump($out);
MESSIAH :)
Ciekawy przykład. Tylko jest w nim mała wada a mianowicie funkcja scandir(). Po co mam skanować kolejny raz katalogi kiedy już wcześniej zrobił to RecursiveDirectoryIterator. Funkcja jest zbędna gdyż należy zoptymalizować kod oraz działanie aplikacji. Już wcześniej myślałem o jej użyciu i wystarczyło mi tylko pobrać same nazwy katalogów oraz podkatalogów a następnie przepuścić przez scandir() i gotowe oraz posortowane. Mi zależy na Iteratorze oraz jak najmniejszym kodzie.

Jest udało mi się w 90% rozwalić ten kod i wklejając dwie linijki mam posortowane prawidłowo około 90% tablicy. Bez żadnych pętli funkcji itp.
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.
Invision Power Board © 2001-2025 Invision Power Services, Inc.