PHP Sortuj tablicę według wartości SubArray

110

Mam następującą strukturę tablicy:

Array
        (
            [0] => Array
                (
                    [configuration_id] => 10
                    [id] => 1
                    [optionNumber] => 3
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )

            [1] => Array
                (
                    [configuration_id] => 9
                    [id] => 1
                    [optionNumber] => 2
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )

            [2] => Array
                (
                    [configuration_id] => 8
                    [id] => 1
                    [optionNumber] => 1
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )
    )

Jaki jest najlepszy sposób uporządkowania tablicy w sposób przyrostowy na podstawie optionNumber?

Więc wyniki wyglądają następująco:

Array
        (
            [0] => Array
                (
                    [configuration_id] => 8
                    [id] => 1
                    [optionNumber] => 1
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )

            [1] => Array
                (
                    [configuration_id] => 9
                    [id] => 1
                    [optionNumber] => 2
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )

            [2] => Array
                (
                    [configuration_id] => 10
                    [id] => 1
                    [optionNumber] => 3
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )
    )
Sjwdavies
źródło

Odpowiedzi:

204

Użyj usort.

function cmp_by_optionNumber($a, $b) {
  return $a["optionNumber"] - $b["optionNumber"];
}

...

usort($array, "cmp_by_optionNumber");

W PHP ≥5.3 powinieneś zamiast tego użyć funkcji anonimowej :

usort($array, function ($a, $b) {
    return $a['optionNumber'] - $b['optionNumber'];
});

Zauważ, że oba powyższe kody zakładają, że $a['optionNumber']jest liczbą całkowitą. Użyj @St. Rozwiązanie Johna Johnsona, jeśli są to struny.


W PHP ≥7.0 użyj operatora statku kosmicznego<=> zamiast odejmowania, aby zapobiec problemom z przepełnieniem / obcięciem.

usort($array, function ($a, $b) {
    return $a['optionNumber'] <=> $b['optionNumber'];
});
kennytm
źródło
1
To nie pomaga mi, ponieważ usort wymaga, aby zapewnić mu funkcję do użycia - co jest trudnym
elementem,
17
Po prostu dał ci funkcję do użycia. I będziesz musiał zaakceptować, że nie zawsze istnieje wbudowana funkcja, która robi to, co chcesz, musisz napisać ją sam. Funkcje porównawcze wymagają po prostu zwrotu 1, 0 lub -1 wskazującego kolejność sortowania dla dwóch elementów.
Tesserex
1
Przyjrzałem się dokładniej usortowi i faktycznie jest całkiem fajny. Napisałem prostą funkcję porównawczą do powyższej, jednak pominięto '=='. Dzięki za pomoc chłopaki
Sjwdavies
3
Teraz także jako zamknięcie: - usort ($ array, function ($ a, $ b) {return $ b ["optionNumber"] - $ a ["optionNumber"];});
Joeri
1
@ KiloumapL'artélon Jeśli wynik to < 0, informuje funkcję sortowania, która apowinna pojawić się wcześniej b. Jeśli jest > 0wtedy bpowinien pojawić się przed a.
kennytm
57

Posługiwać się usort

 usort($array, 'sortByOption');
 function sortByOption($a, $b) {
   return strcmp($a['optionNumber'], $b['optionNumber']);
 }
St. John Johnson
źródło
7
@BenSinclair, to dlatego, że rozwiązanie Kenny'ego dotyczy liczb, to rozwiązanie dotyczy łańcuchów. Obie są poprawne :-) +1 dla tej alternatywy.
kubilay,
Do sortowania bez rozróżniania wielkości liter użyj strcasecmp zamiast strcmp
user570605
Czy możemy zdefiniować klucz dla drugiego rzędu w tablicy oznacza, że ​​najpierw sortujemy za pomocą optionNumber, a następnie sortujemy za pomocą lastUpdated. Jak to zrobić?
Bhavin Thummar
16

Użyłem obu rozwiązań KennyTM i AJ Quick i wymyśliłem funkcję, która może pomóc w tym problemie w wielu przypadkach, takich jak używanie sortowania lub zachowywania kluczy ASC lub DESC lub jeśli masz obiekty jako elementy podrzędne tablicy .

Oto ta funkcja (działa dla PHP7 i nowszych z powodu operatora statku kosmicznego):

/**
 * @param array $array
 * @param string $value
 * @param bool $asc - ASC (true) or DESC (false) sorting
 * @param bool $preserveKeys
 * @return array
 * */
function sortBySubValue($array, $value, $asc = true, $preserveKeys = false)
{
    if ($preserveKeys) {
        $c = [];
        if (is_object(reset($array))) {
            foreach ($array as $k => $v) {
                $b[$k] = strtolower($v->$value);
            }
        } else {
            foreach ($array as $k => $v) {
                $b[$k] = strtolower($v[$value]);
            }
        }
        $asc ? asort($b) : arsort($b);
        foreach ($b as $k => $v) {
            $c[$k] = $array[$k];
        }
        $array = $c;
    } else {
        if (is_object(reset($array))) {
            usort($array, function ($a, $b) use ($value, $asc) {
                return $a->{$value} == $b->{$value} ? 0 : ($a->{$value} <=> $b->{$value}) * ($asc ? 1 : -1);
            });
        } else {
            usort($array, function ($a, $b) use ($value, $asc) {
                return $a[$value] == $b[$value] ? 0 : ($a[$value] <=> $b[$value]) * ($asc ? 1 : -1);
            });
        }
    }

    return $array;
}

Stosowanie:

sortBySubValue($array, 'optionNumber', true, false);

Edytować

Pierwszą część można przepisać za pomocą, uasort()a funkcja będzie krótsza (działa dla PHP7 i wyższych z powodu operatora statku kosmicznego):

/**
 * @param array $array
 * @param string $value
 * @param bool $asc - ASC (true) or DESC (false) sorting
 * @param bool $preserveKeys
 * @return array
 * */
function sortBySubValue($array, $value, $asc = true, $preserveKeys = false)
{
    if (is_object(reset($array))) {
        $preserveKeys ? uasort($array, function ($a, $b) use ($value, $asc) {
            return $a->{$value} == $b->{$value} ? 0 : ($a->{$value} <=> $b->{$value}) * ($asc ? 1 : -1);
        }) : usort($array, function ($a, $b) use ($value, $asc) {
            return $a->{$value} == $b->{$value} ? 0 : ($a->{$value} <=> $b->{$value}) * ($asc ? 1 : -1);
        });
    } else {
        $preserveKeys ? uasort($array, function ($a, $b) use ($value, $asc) {
            return $a[$value] == $b[$value] ? 0 : ($a[$value] <=> $b[$value]) * ($asc ? 1 : -1);
        }) : usort($array, function ($a, $b) use ($value, $asc) {
            return $a[$value] == $b[$value] ? 0 : ($a[$value] <=> $b[$value]) * ($asc ? 1 : -1);
        });
    }
    return $array;
}
Pigalev Pavel
źródło
To najlepsza najbardziej przydatna odpowiedź, powinna być na górze;)
Edi Budimilic
@EdiBudimilic dziękuję, doceniam to!
Swoją
1
Aby to zadziałało, musiałem użyć >(większe niż) zamiast -(minus) podczas porównywania $ai $bwartości, ponieważ porównywałem ciągi. Jednak nadal działa.
James
1
@James masz rację. Zmieniłem odpowiedź i dodałem użycie operatora statku kosmicznego (<=>). Teraz powinno działać dobrze.
Pigalev Pavel
Czy istnieje sposób, aby uczynić tę sprawę niewrażliwą?
loeffel
4

Klawisze są usuwane podczas korzystania z funkcji takiej jak te powyżej. Jeśli klucze są ważne, zachowa je następująca funkcja ... ale wszystkie pętle są dość nieefektywne.

function subval_sort($a,$subkey) {
    foreach($a as $k=>$v) {
        $b[$k] = strtolower($v[$subkey]);
    }
    asort($b);
    foreach($b as $key=>$val) {
        $c[$key] = $a[$key];
    }
    return $c;
}
$array = subval_sort($array,'optionNumber');

Jeśli chcesz od największego do najmniejszego, użyj opcji arsort zamiast asortymentu.

Źródło kodu: http://www.firsttube.com/read/sorting-a-multi-dimensional-array-with-php/

AJ Quick
źródło
4

Korzystanie z array_multisort (), array_map ()

array_multisort(array_map(function($element) {
      return $element['optionNumber'];
  }, $array), SORT_ASC, $array);

print_r($array);

PRÓBNY

Ghanshyam Nakiya
źródło
2
To po prostu działa bardzo łatwo. Dziękuję Ci. Wszystko, co musiałem zrobić, to zmienić nazwę mojej kolumny i zadziałało.
Kobus Myburgh,
2
To również zachowuje klucze dla tablicy nadrzędnej
JonnyS
3

PHP 5.3+

usort($array, function($a,$b){ return $a['optionNumber']-$b['optionNumber'];} );
Samer Ata
źródło