Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]usort Pomoc w napisaniu funkcji sortującej
Forum PHP.pl > Forum > Przedszkole
arzach
Witam mam taki kod
  1. $a = array (
  2. array ('M' => 3, 'MB' => 1),
  3. array ('M' => 3, 'MB' => 3),
  4. array ('M' => 2),
  5. array ('M' => 2, 'MB' => 1),
  6. array ('M' => 2, 'MB' => 3),
  7. array ('M' => 3),
  8. array ('M' => 3, 'MB' => 2)
  9. );
  10.  
  11.  
  12.  
  13. function mysort1 ($x, $y) {
  14. return ($x['M'] < $y['M']);
  15. }
  16.  
  17. usort ($a, 'mysort1');
  18. echo '<pre>';
  19. print_r($a);
  20. echo '</pre>';


I potrzebuje posortować najpierw po M a potem gdy istnieje MB to to MB ale tak gdy jest tylko M to M jest wyżej Czyli tablica jaką chce uzyskać

  1. $a = array (
  2. array ('M' => 3),
  3. array ('M' => 3, 'MB' => 3),
  4. array ('M' => 3, 'MB' => 2),
  5. array ('M' => 3, 'MB' => 1),
  6. array ('M' => 2),
  7. array ('M' => 2, 'MB' => 3),
  8. array ('M' => 2, 'MB' => 1)
  9. );


Proszę o pomoc.
thek
Pomyśl... Skoro manual daje jako przykład:
  1. function cmp($a, $b) {
  2. if ($a == $b) {
  3. return 0;
  4. }
  5. return ($a < $b) ? -1 : 1;
  6. }

To jak powinno to wyglądać, skoro a i b będą teraz same tablicami? smile.gif Bardzo podobnie, ale bedzie to minimalnie bardziej rozbudowane pamiętając, że 0 to elementy równe, wartość ujemna to większy element $b, a wartość dodatnia to większy element $a.
  1. function cmp($a, $b) {
  2. if ($a['M'] == $b['M']) { //gdy M równe to będzie konieczne dodatkowe sortowanie...
  3. if( array_key_exists( $a['MB'] && array_key_exists( $a['MB'] ) ) { //sprawdzanie czy oba elementy mają MB...
  4. return ( $a['MB'] < $b['MB'] ) ? -1 : 1; //jeśli oba mają MB to sortujemy po nich
  5. } else { // jeśli jedno nie będzie miało MB to ono pójdzie wyżej...
  6. return ( !array_key_exists( $a['MB'] ) ? 1 : -1 ); //sprawdzenie istnienia MB - tu trzeba logiki... wyjaśnię ją pod kodem :) WYJAŚNIENIE NIŻEJ
  7. }
  8. } else { // gdy nie to proste porówanie dla M wskaże co gdzie :)
  9. return ( $a['M'] < $b['M'] ) ? -1 : 1;
  10. }
  11. };
Trickiem jest tu konieczność sprawdzenia tylko jednego elementu jeśli choć jeden z nich nie posiada MB. Jeśli MB nie ma w $a to on idzie wyżej, jeśli nie ma go $b, to on idzie wyżej, a jeśli nie mają go oba to nie ma znaczenia co jak będzie w kolejności, bo są w takim wypadku oba równe. Stąd od razu z góry zdecydowałem, że jeśli nie ma $a['MB'] to zwróci zawsze, iż $a jest większy, bez sprawdzania $b. Takie uproszczenie logiczne. Sami zobaczcie...
$a nie ma MB, $b ma je - sprawdzenie $a (nie ma) - $a jest większe
$a ma MB, $b nie ma go - sprawdzenie $a (ma) - $b jest większe
$a nie ma MB, $b nie ma - sprawdzenie $a (nie ma) - $a jest większe, choć de facto sa sobie równe smile.gif
$a ma MB, $b ma - sprawdzenie pomiędzy elementami, który ma większy MB, ale to już spełnienie warunku IF mnieco wyżej, a więc nie w gestii naszego ELSE.
Tylko po co robić kolejny if w środku, który tylko pogorszy wydajność? Co za różnica czy $a czy $b ustawione będzie jako pierwsze, skoro nie rozróżnimy ich i tak bo nie zachowujemy przy tym typie sortowaniu kluczy czy czegokolwiek? Innymi słowy porównywanie MB obu elementów jest zupełnie zbędne. To samo się tyczy innych porównań, bo jak sam zapewne zauważyłeś, nigdzie w kodzie nie zwracam 0. Jest to kompletnie niepotrzebny przypadek. Zwracanie 0 nie ma w zasadzie uzasadnienia wydajnościowego tak naprawdę. Może są przypadki, gdzie logika tego wymaga, ale ciężko mi jakiś wymyślić.

EDIT: Nie ufam tutaj funkcji isset, ponieważ zwraca false w przypadku gdy klucz istnieje, ale ma wartość NULL. Dlatego używam dla tablic pewniejszej array_key_exists. Sam sprawdź wink.gif
  1. $a['klucz'] = NULL;
  2. var_dump( isset( $a['klucz'] ) ); //false
  3. var_dump( array_key_exists( 'klucz', $a ) ); //true
arzach
Ok mam taki kod trochę poprawiłem i działa
  1. $array = array (
  2. array ('Punkty' => 3, 'mecze_bezposrednie' => array('LM' => 1, 'PktB' => 1, 'BRB' => 0, 'BBZ' => 0), 'RB' => 3),
  3. array ('Punkty' => 3, 'mecze_bezposrednie' => array('LM' => 1, 'PktB' => 1, 'BRB' => 0, 'BBZ' => 1), 'RB' => 3),
  4. array ('Punkty' => 3, 'mecze_bezposrednie' => array('LM' => 2, 'PktB' => 2, 'BRB' => 0, 'BBZ' => 1), 'RB' => 3),
  5. array ('Punkty' => 3, 'RB' => 2),
  6. array ('Punkty' => 2, 'RB' => 3),
  7. array ('Punkty' => 2, 'RB' => 1),
  8. array ('Punkty' => 2, 'mecze_bezposrednie' => array('LM' => 1, 'PktB' => 0, 'BRB' => -6, 'BBZ' => 0), 'RB' => 3),
  9. array ('Punkty' => 2, 'mecze_bezposrednie' => array('LM' => 1, 'PktB' => 3, 'BRB' => 6, 'BBZ' => 6), 'RB' => 3),
  10. array ('Punkty' => 2, 'RB' => 3)
  11. );
  12.  
  13.  
  14. function cmp($a, $b) {
  15. if ($a['Punkty'] == $b['Punkty']) {
  16.  
  17. if(array_key_exists('mecze_bezposrednie', $a) && array_key_exists('mecze_bezposrednie', $b)){
  18. return ( $a['mecze_bezposrednie']['LM'] < $b['mecze_bezposrednie']['LM'] ) ? -1 : 1;
  19. } else {
  20.  
  21. return ( !array_key_exists('mecze_bezposrednie', $b) ? 1 : -1 );
  22.  
  23. }
  24.  
  25.  
  26.  
  27. } else {
  28. return ( $a['Punkty'] > $b['Punkty'] ) ? -1 : 1;
  29. }
  30. }
  31.  
  32. usort ($array, 'cmp');



Ale jak teraz dorobić gdy LM jest takie same to ma sortować po Pkt, BRB, BBZ meczę się z tym od rana i nic nie wychodzi

Próbowałem tak
  1. function cmp($a, $b) {
  2. if ($a['punkty'] == $b['punkty']) {
  3. if(array_key_exists('mecze_bezposrednie', $a) && array_key_exists('mecze_bezposrednie', $b)){
  4. return ( $a['mecze_bezposrednie']['LM'] < $b['mecze_bezposrednie']['LM'] ) ? -1 : 1;
  5. } elseif(array_key_exists('mecze_bezposrednie', $a) && array_key_exists('mecze_bezposrednie', $b) && $a['mecze_bezposrednie']['LM'] == $b['mecze_bezposrednie']['LM']){
  6.  
  7. return ( $a['mecze_bezposrednie']['PktB'] < $b['mecze_bezposrednie']['PktB'] ) ? -1 : 1;
  8.  
  9. } elseif(array_key_exists('mecze_bezposrednie', $a) && array_key_exists('mecze_bezposrednie', $b) && $a['mecze_bezposrednie']['LM'] == $b['mecze_bezposrednie']['LM'] && $a['mecze_bezposrednie']['PktB'] == $b['mecze_bezposrednie']['PktB']){
  10.  
  11. return ( $a['mecze_bezposrednie']['BRB'] < $b['mecze_bezposrednie']['BRB'] ) ? -1 : 1;
  12.  
  13. } elseif(array_key_exists('mecze_bezposrednie', $a) && array_key_exists('mecze_bezposrednie', $b) && $a['mecze_bezposrednie']['LM'] == $b['mecze_bezposrednie']['LM'] && $a['mecze_bezposrednie']['PktB'] == $b['mecze_bezposrednie']['PktB'] && $a['mecze_bezposrednie']['BRB'] == $b['mecze_bezposrednie']['BRB']){
  14.  
  15. return ( $a['mecze_bezposrednie']['BBZ'] < $b['mecze_bezposrednie']['BBZ'] ) ? -1 : 1;
  16.  
  17. } else {
  18. return ( !array_key_exists('mecze_bezposrednie', $b) ? 1 : -1 );
  19. }
  20.  
  21. } else {
  22. return ( $a['punkty'] > $b['punkty'] ) ? -1 : 1;
  23. }
  24. }
  25.  


ale nie działa nie mam pojęcia dla czego
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.