Ordina array PHP per valore di sottoarray


110

Ho la seguente struttura ad array:

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
                )
    )

Qual è il modo migliore per ordinare l'array in modo incrementale, in base a optionNumber?

Quindi i risultati assomigliano a:

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
                )
    )

Risposte:


204

Usa usort.

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

...

usort($array, "cmp_by_optionNumber");

In PHP ≥5.3, dovresti invece usare una funzione anonima :

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

Si noti che entrambi i codici sopra assumono che $a['optionNumber']sia un numero intero. Usa @St. La soluzione di John Johnson se sono stringhe.


In PHP ≥7.0, usa l' operatore astronave<=> invece della sottrazione per evitare problemi di overflow / troncamento.

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

1
Questo non mi aiuta molto perché usort richiede che gli fornisca una funzione da usare - che è la parte difficile che non riesco a capire
— Sjwdavies

17
Beh, ti ha appena dato la funzione da usare. E dovrai accettare che non c'è sempre una funzione incorporata per fare quello che vuoi, devi scriverla tu stesso. Le funzioni di confronto richiedono solo un ritorno di 1, 0 o -1 che indica l'ordinamento per due elementi.
— Tesserex

1
Ho approfondito Usort e in realtà è piuttosto interessante. Ho scritto una semplice funzione di confronto con quella sopra, ma ho perso il '=='. Grazie per l'aiuto ragazzi
— Sjwdavies

3
Ora anche come chiusura: - usort ($ array, function ($ a, $ b) {return $ b ["optionNumber"] - $ a ["optionNumber"];});
— Joeri

1
@ KiloumapL'artélon Se il risultato è < 0, indica la funzione di ordinamento che adovrebbe apparire prima b. Se è > 0allora bdovrebbe comparire davanti a.
— kennytm

57

Uso usort

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

7
@ BenSinclair, questo perché la soluzione di Kenny è per i numeri, questa soluzione è per le stringhe. Sono entrambi corretti :-) +1 per questa alternativa.
— kubilay

Per l'ordinamento senza distinzione tra maiuscole e minuscole, utilizzare strcasecmp invece di strcmp
— user570605

possiamo definire la chiave per il secondo ordine in array significa che eseguiamo prima l'ordinamento con optionNumber quindi l'ordinamento con lastUpdated. Come puoi fare questa cosa?
— Bhavin Thummar

16

Ho usato entrambe le soluzioni di KennyTM e AJ Quick e ho creato una funzione che può aiutare in questo problema per molti casi come l' uso dell'ordinamento ASC o DESC o della conservazione delle chiavi o se si hanno oggetti come figli dell'array .

Ecco questa funzione (funziona per PHP7 e versioni successive a causa dell'operatore di astronave):

/**
 * @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;
}

Uso:

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

modificare

La prima parte può essere riscritta usando uasort()e la funzione sarà più breve (funziona per PHP7 e superiori a causa dell'operatore di astronave):

/**
 * @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;
}

Questa è la migliore risposta più utile qui, dovrebbe essere in cima;)
— Edi Budimilic

@EdiBudimilic grazie, lo apprezzo! A proposito, ho aggiornato la mia risposta e ho aggiunto una versione più breve di questa funzione :)
— Pigalev Pavel

1
Per far funzionare questo per me, ho dovuto usare >(maggiore di) invece di -(meno) durante il confronto $ae i $bvalori poiché stavo confrontando le stringhe. Funziona ancora comunque.
— James

1
@ James hai ragione. Ho cambiato la risposta e aggiunto l'uso dell'operatore di astronave (<=>). Ora dovrebbe funzionare bene.
— Pigalev Pavel

C'è un modo per rendere questo caso insensibile?
— loeffel

4

I tasti vengono rimossi quando si utilizza una funzione come quelle sopra. Se i tasti sono importanti, la seguente funzione la manterrebbe ... ma i cicli foreach sono piuttosto inefficienti.

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');

Usa arsort invece di asort se vuoi dall'alto verso il basso.

Credito codice: http://www.firsttube.com/read/sorting-a-multi-dimensional-array-with-php/


4

Utilizzando array_multisort (), array_map ()

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

print_r($array);

DEMO


2
Funziona molto facilmente. Grazie. Tutto quello che dovevo fare era cambiare il nome della mia colonna e ha funzionato.
— Kobus Myburgh

2
Ciò preserva anche le chiavi per l'array padre
— JonnyS

3

PHP 5.3+

usort($array, function($a,$b){ return $a['optionNumber']-$b['optionNumber'];} );
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.