Come posso ordinare array e dati in PHP?


292

Questa domanda è intesa come riferimento per domande sull'ordinamento di array in PHP. È facile pensare che il tuo caso particolare sia unico e degno di una nuova domanda, ma la maggior parte sono in realtà variazioni minori di una delle soluzioni in questa pagina.

Se la tua domanda è chiusa come duplicata di questa, chiedi di riaprirla solo se puoi spiegare perché differisce notevolmente da tutto quanto sotto.

Come posso ordinare un array in PHP?
Come posso ordinare un array complesso in PHP?
Come posso ordinare una matrice di oggetti in PHP?


  1. Matrici unidimensionali di base; Incl. Matrici multidimensionali, incl. matrici di oggetti; Incl. Ordinamento di un array basato su un altro

  2. Ordinamento con SPL

  3. Ordinamento stabile

Per la risposta pratica usando le funzioni esistenti di PHP vedi 1., per la risposta accademica in dettaglio sugli algoritmi di ordinamento (che implementano le funzioni di PHP e che potresti aver bisogno per casi davvero molto complessi), vedi 2.


@jterry Esattamente, è per questo che ho fatto questo per avere finalmente una buona domanda di riferimento da chiudere. Rispondere a ogni singolo fiocco di neve singolarmente non aiuta nessuno. :)
ingannare

3
Penso che la gente dovrebbe semplicemente dare un'occhiata a php.net
Alexander Jardim,

@Alex Ha! Assolutamente. Il problema è: nessuno RTFM. : D
inganno

2
Abbiamo già queste risposte, ti suggerisco di elencare le migliori risposte all'interno di ogni risposta qui invece di duplicare (o riscrivere) il contenuto. Inoltre, le matrici tendono a essere viste individualmente, quindi il lavoro rimane per chiudere il voto contro i duplicati in ogni caso.
Hakre,

1
@deceze: se nessuno RTFM, nessuno lo farà anche RTFQA - domande e risposte esistenti :)
hakre,

Risposte:


164

Matrici unidimensionali di base

$array = array(3, 5, 2, 8);

Funzioni di ordinamento applicabili:

  • sort
  • rsort
  • asort
  • arsort
  • natsort
  • natcasesort
  • ksort
  • krsort

La differenza tra questi è semplicemente se vengono mantenute le associazioni di valori-chiave (le " a" funzioni), se ordina da basso ad alto o inverso (" r"), se ordina valori o chiavi (" k") e come confronta i valori (" nat" vs. normale). Vedere http://php.net/manual/en/array.sorting.php per una panoramica e collegamenti a ulteriori dettagli.

Matrici multidimensionali, comprese matrici di oggetti

$array = array(
    array('foo' => 'bar', 'baz' => 42),
    array('foo' => ...,   'baz' => ...),
    ...
);

Se vuoi ordinare $array base al tasto "pippo" di ciascuna voce, è necessaria una funzione di confronto personalizzata . Le sortfunzioni precedenti e correlate funzionano su valori semplici che sanno confrontare e ordinare. PHP non "semplicemente" sa cosa fare di un valore complesso come array('foo' => 'bar', 'baz' => 42)se; quindi devi dirlo.

Per farlo, devi creare un funzione di confronto . Tale funzione accetta due elementi e deve restituire 0se tali elementi sono considerati uguali, un valore inferiore rispetto a 0se il primo valore è inferiore e un valore superiore rispetto a 0se il primo valore è superiore. Questo è tutto ciò che serve:

function cmp(array $a, array $b) {
    if ($a['foo'] < $b['foo']) {
        return -1;
    } else if ($a['foo'] > $b['foo']) {
        return 1;
    } else {
        return 0;
    }
}

Spesso, si desidera utilizzare una funzione anonima come callback. Se vuoi usare un metodo o un metodo statico, vedi gli altri modi per specificare un callback in PHP .

Quindi utilizzare una di queste funzioni:

Ancora una volta, differiscono solo per il fatto che mantengano le associazioni valore-chiave e ordinino per valori o chiavi. Leggi la loro documentazione per i dettagli.

Esempio di utilizzo:

usort($array, 'cmp');

usortprenderà due elementi dall'array e chiamerà la tua cmpfunzione con loro. Così cmp()sarà chiamato con $acome array('foo' => 'bar', 'baz' => 42)e $bcome un altro array('foo' => ..., 'baz' => ...). La funzione quindi restituisce a usortquale dei valori era maggiore o se erano uguali. usortripete questo processo passando valori diversi per $ae $bfinché l'array non viene ordinato. La cmpfunzione verrà chiamata molte volte, almeno quante volte ci sono valori in $array, con diverse combinazioni di valori per $ae $bogni volta.

Per abituarti a questa idea, prova questo:

function cmp($a, $b) {
    echo 'cmp called with $a:', PHP_EOL;
    var_dump($a);
    echo 'and $b:', PHP_EOL;
    var_dump($b);
}

Tutto quello che hai fatto è stato definire un modo personalizzato per confrontare due elementi, questo è tutto ciò di cui hai bisogno. Funziona con tutti i tipi di valori.

A proposito, questo funziona su qualsiasi valore, i valori non devono essere array complessi. Se hai un confronto personalizzato che vuoi fare, puoi farlo anche su un semplice array di numeri.

sort ordina per riferimento e non restituisce nulla di utile!

Si noti che l'array si ordina sul posto , non è necessario assegnare il valore restituito a nulla. $array = sort($array)sostituirà l'array con true, non con un array ordinato. sort($array);Funziona e basta .

Confronti numerici personalizzati

Se desideri ordinare in base alla bazchiave, che è numerica, tutto ciò che devi fare è:

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

Grazie a The PoWEr oF MATH questo restituisce un valore <0, 0 o> 0 a seconda che $asia inferiore a, uguale o maggiore di $b.

Si noti che questo non funzionerà bene per i floatvalori, poiché saranno ridotti a inte perderanno la precisione. Uso esplicito -1, 0e1 restituire i valori invece.

Oggetti

Se hai una matrice di oggetti, funziona allo stesso modo:

function cmp($a, $b) {
    return $a->baz - $b->baz;
}

funzioni

Puoi fare tutto ciò di cui hai bisogno all'interno di una funzione di confronto, incluse le funzioni di chiamata:

function cmp(array $a, array $b) {
    return someFunction($a['baz']) - someFunction($b['baz']);
}

stringhe

Una scorciatoia per la prima versione di confronto delle stringhe:

function cmp(array $a, array $b) {
    return strcmp($a['foo'], $b['foo']);
}

strcmpfa esattamente quello che ci si aspetta da cmpqui, ritorna -1, 0o 1.

Operatore di astronave

PHP 7 ha introdotto l' operatore dell'astronave , che unifica e semplifica uguale / più piccolo / più grande dei confronti tra i tipi:

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

Ordinamento per più campi

Se vuoi ordinare principalmente per foo, ma se fooè uguale per due elementi ordina per baz:

function cmp(array $a, array $b) {
    if (($cmp = strcmp($a['foo'], $b['foo'])) !== 0) {
        return $cmp;
    } else {
        return $a['baz'] - $b['baz'];
    }
}

Per quelli familiari, questo equivale a una query SQL con ORDER BY foo, baz.
Vedi anche questa versione abbreviata molto accurata e come creare dinamicamente una simile funzione di confronto per un numero arbitrario di chiavi .

Ordinamento in un ordine manuale, statico

Se vuoi ordinare gli elementi in un "ordine manuale" come "pippo", "bar", "baz" :

function cmp(array $a, array $b) {
    static $order = array('foo', 'bar', 'baz');
    return array_search($a['foo'], $order) - array_search($b['foo'], $order);
}

Per tutto quanto sopra, se stai usando PHP 5.3 o versioni successive (e dovresti davvero), usa le funzioni anonime per un codice più breve e per evitare di avere un'altra funzione globale fluttuante:

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

Ecco come può essere semplice l'ordinamento di un complesso array multidimensionale. Ancora una volta, basti pensare in termini di insegnamento a PHP come dire quale dei due elementi è "maggiore" ; lascia che PHP faccia l'ordinamento effettivo.

Anche per tutto quanto sopra, per passare dall'ordine crescente a quello decrescente basta scambiare gli argomenti $ae $b. Per esempio:

return $a['baz'] - $b['baz']; // ascending
return $b['baz'] - $a['baz']; // descending

Ordinamento di un array basato su un altro

E poi c'è il peculiare array_multisort, che ti consente di ordinare un array in base a un altro:

$array1 = array( 4,   6,   1);
$array2 = array('a', 'b', 'c');

Il risultato atteso qui sarebbe:

$array2 = array('c', 'a', 'b');  // the sorted order of $array1

Usa array_multisortper arrivarci:

array_multisort($array1, $array2);

A partire da PHP 5.5.0 puoi usare array_columnper estrarre una colonna da un array multidimensionale e ordinare l'array su quella colonna:

array_multisort(array_column($array, 'foo'), SORT_DESC, $array);

A partire da PHP 7.0.0 puoi anche estrarre proprietà da una matrice di oggetti.


Se hai casi più comuni, sentiti libero di modificare questa risposta.


La funzione di confronto numerico non funziona per i valori float; Sono sicuro che sai cosa intendo :)
Ja͢ck,

1
Per l'ordine statico, vorrei applicare array_flip()per fare una ricerca più rapida della posizione, ad es. $order[$a['foo']]Anziché array_search($a['foo'], $order).
Ja͢ck,

Potrebbe essere un po 'una grande modifica: gist.github.com/Rizier123/24a6248758b53245a63e839d8e08a32b ma se pensi che sia un miglioramento e ho incluso tutto l'essenziale posso applicarlo.
Rizier123,

@ Rizier123 Certamente applaudo lo sforzo, è un ottimo commento; ma lo preferirei se lo pubblicassi come risposta separata, anche se è molto simile. La tua riscrittura contiene molti dettagli (passa per riferimento, grande tabella ecc.), Ma quel dettaglio distrae dall'introduzione regolare all'argomento principale del funzionamento della funzione di confronto, IMHO. Mi riferisco esplicitamente al manuale più volte di proposito, perché è qui che si dovrebbero cercare tali dettagli; non c'è bisogno di ripeterlo qui e distrarre dall'idea di base che sto cercando di trasmettere.
Inganno

@deceze La sfida principale, poiché si tratta di domande e risposte di riferimento, è quella di visualizzare le informazioni nel modo più compatto e leggibile possibile e di facilitare la ricerca delle funzioni di ordinamento da parte degli utenti. Ho modificato alcune cose: gist.github.com/Rizier123/24a6248758b53245a63e839d8e08a32b ma devo ancora pensarci, se è utile e prezioso pubblicarlo come risposta separata, poiché è un contenuto molto simile
Rizier123

139

Beh, la maggior parte dei metodi di base sono già coperti dall'inganno. Proverei a guardare altri tipi di ordinamento

Ordinamento con SPL

SplHeap

class SimpleHeapSort extends SplHeap {
    public function compare($a, $b) {
        return strcmp($a, $b);
    }
}

// Let's populate our heap here (data of 2009)
$heap = new SimpleHeapSort();
$heap->insert("a");
$heap->insert("b");
$heap->insert("c");

echo implode(PHP_EOL, iterator_to_array($heap));

Produzione

c
b
a

SplMaxHeap

La classe SplMaxHeap fornisce le funzionalità principali di un heap, mantenendo il massimo in alto.

$heap = new SplMaxHeap();
$heap->insert(1);
$heap->insert(2);
$heap->insert(3);

SplMinHeap

La classe SplMinHeap fornisce le funzionalità principali di un heap, mantenendo il minimo in cima.

$heap = new SplMinHeap ();
$heap->insert(3);
$heap->insert(1);
$heap->insert(2);

Altri tipi di ordinamento

Bubble Sort

Dalla articolo di Wikipedia su Bubble Sort:

L'ordinamento a bolle, a volte erroneamente indicato come ordinamento di affondamento, è un semplice algoritmo di ordinamento che funziona facendo scorrere ripetutamente l'elenco per essere ordinati, confrontando ciascuna coppia di elementi adiacenti e scambiandoli se sono nell'ordine sbagliato. Il passaggio attraverso l'elenco viene ripetuto fino a quando non sono necessari scambi, il che indica che l'elenco è ordinato. L'algoritmo prende il nome dal modo in cui gli elementi più piccoli "bolle" in cima all'elenco. Poiché utilizza solo confronti per operare sugli elementi, è un ordinamento di confronto. Sebbene l'algoritmo sia semplice, la maggior parte degli altri algoritmi di ordinamento sono più efficienti per elenchi di grandi dimensioni.

function bubbleSort(array $array) {
    $array_size = count($array);
    for($i = 0; $i < $array_size; $i ++) {
        for($j = 0; $j < $array_size; $j ++) {
            if ($array[$i] < $array[$j]) {
                $tem = $array[$i];
                $array[$i] = $array[$j];
                $array[$j] = $tem;
            }
        }
    }
    return $array;
}

Ordinamento di selezione

Dalla alle voci di Wikipedia ordinamento per selezione:

In informatica, l'ordinamento per selezione è un algoritmo di ordinamento, in particolare un ordinamento di confronto sul posto. Ha una complessità temporale O (n2), che lo rende inefficiente su elenchi di grandi dimensioni e generalmente ha prestazioni peggiori rispetto all'ordinamento di inserzione simile. L'ordinamento della selezione è noto per la sua semplicità e presenta vantaggi prestazionali rispetto ad algoritmi più complicati in determinate situazioni, in particolare dove la memoria ausiliaria è limitata.

function selectionSort(array $array) {
    $length = count($array);
    for($i = 0; $i < $length; $i ++) {
        $min = $i;
        for($j = $i + 1; $j < $length; $j ++) {
            if ($array[$j] < $array[$min]) {
                $min = $j;
            }
        }
        $tmp = $array[$min];
        $array[$min] = $array[$i];
        $array[$i] = $tmp;
    }
    return $array;
}

Ordinamento per inserzione

Dal voci di Wikipedia Insertion sort:

L'ordinamento per inserzione è un semplice algoritmo di ordinamento che crea l'array (o l'elenco) ordinato finale un elemento alla volta. È molto meno efficiente su elenchi di grandi dimensioni rispetto agli algoritmi più avanzati come quicksort, heapsort o merge sort. Tuttavia, l'ordinamento per inserzione offre numerosi vantaggi:

function insertionSort(array $array) {
    $count = count($array);
    for($i = 1; $i < $count; $i ++) {

        $j = $i - 1;
        // second element of the array
        $element = $array[$i];
        while ( $j >= 0 && $array[$j] > $element ) {
            $array[$j + 1] = $array[$j];
            $array[$j] = $element;
            $j = $j - 1;
        }
    }
    return $array;
}

shellsort

Dal voci di Wikipedia Shellsort:

Shellsort, noto anche come ordinamento di Shell o metodo di Shell, è un ordinamento di confronto sul posto. Si generalizza una sorta di scambio, come l'inserimento o l'ordinamento a bolle, avviando il confronto e lo scambio di elementi con elementi che sono distanti prima di finire con elementi vicini.

function shellSort(array $array) {
    $gaps = array(
            1,
            2,
            3,
            4,
            6
    );
    $gap = array_pop($gaps);
    $length = count($array);
    while ( $gap > 0 ) {
        for($i = $gap; $i < $length; $i ++) {
            $tmp = $array[$i];
            $j = $i;
            while ( $j >= $gap && $array[$j - $gap] > $tmp ) {
                $array[$j] = $array[$j - $gap];
                $j -= $gap;
            }
            $array[$j] = $tmp;
        }
        $gap = array_pop($gaps);
    }
    return $array;
}

Comb ordinamento

Dalla alle voci di Wikipedia pettine sorta:

Comb sort è un algoritmo di ordinamento relativamente semplice originariamente progettato da Wlodzimierz Dobosiewicz nel 1980. Successivamente è stato riscoperto da Stephen Lacey e Richard Box nel 1991. Comb ordinamento migliora l'ordinamento a bolle.

function combSort(array $array) {
    $gap = count($array);
    $swap = true;
    while ( $gap > 1 || $swap ) {
        if ($gap > 1)
            $gap /= 1.25;
        $swap = false;
        $i = 0;
        while ( $i + $gap < count($array) ) {
            if ($array[$i] > $array[$i + $gap]) {
                // swapping the elements.
                list($array[$i], $array[$i + $gap]) = array(
                        $array[$i + $gap],
                        $array[$i]
                );
                $swap = true;
            }
            $i ++;
        }
    }
    return $array;
}

Unisci ordinamento

Dalla alle voci di Wikipedia merge sort:

Nell'informatica, un ordinamento di tipo merge (anch'esso comunemente scritto mergesort) è un algoritmo di ordinamento basato sul confronto O (n log n). La maggior parte delle implementazioni produce un ordinamento stabile, il che significa che l'implementazione conserva l'ordine di input di elementi uguali nell'output ordinato

function mergeSort(array $array) {
    if (count($array) <= 1)
        return $array;

    $left = mergeSort(array_splice($array, floor(count($array) / 2)));
    $right = mergeSort($array);

    $result = array();

    while ( count($left) > 0 && count($right) > 0 ) {
        if ($left[0] <= $right[0]) {
            array_push($result, array_shift($left));
        } else {
            array_push($result, array_shift($right));
        }
    }
    while ( count($left) > 0 )
        array_push($result, array_shift($left));

    while ( count($right) > 0 )
        array_push($result, array_shift($right));

    return $result;
}

quicksort

Dalla alle voci di Wikipedia Quicksort:

Quicksort, o ordinamento per lo scambio di partizioni, è un algoritmo di ordinamento sviluppato da Tony Hoare che, in media, effettua confronti O (n log n) per ordinare n elementi. Nel peggiore dei casi, effettua confronti O (n2), sebbene questo comportamento sia raro.

function quickSort(array $array) {
    if (count($array) == 0) {
        return $array;
    }
    $pivot = $array[0];
    $left = $right = array();
    for($i = 1; $i < count($array); $i ++) {
        if ($array[$i] < $pivot) {
            $left[] = $array[$i];
        } else {
            $right[] = $array[$i];
        }
    }
    return array_merge(quickSort($left), array(
            $pivot
    ), quickSort($right));
}

Ordinamento di permutazione

Dalla alle voci di Wikipedia Permutazione sorta:

Ordinamento delle permutazioni, che procede generando le possibili permutazioni della matrice / lista di input fino a scoprire quella ordinata.

function permutationSort($items, $perms = array()) {
    if (empty($items)) {
        if (inOrder($perms)) {
            return $perms;
        }
    } else {
        for($i = count($items) - 1; $i >= 0; -- $i) {
            $newitems = $items;
            $newperms = $perms;
            list($foo) = array_splice($newitems, $i, 1);
            array_unshift($newperms, $foo);
            $res = permutationSort($newitems, $newperms);
            if ($res) {
                return $res;
            }
        }
    }
}

function inOrder($array) {
    for($i = 0; $i < count($array); $i ++) {
        if (isset($array[$i + 1])) {
            if ($array[$i] > $array[$i + 1]) {
                return False;
            }
        }
    }
    return True;
}

Ordinamento Radix

Dalla alle voci di Wikipedia Radix sorta:

In informatica, l'ordinamento radix è un algoritmo di ordinamento intero non comparativo che ordina i dati con chiavi intere raggruppando le chiavi in ​​base alle singole cifre che condividono la stessa posizione e valore significativi.

// Radix Sort for 0 to 256
function radixSort($array) {
    $n = count($array);
    $partition = array();

    for($slot = 0; $slot < 256; ++ $slot) {
        $partition[] = array();
    }

    for($i = 0; $i < $n; ++ $i) {
        $partition[$array[$i]->age & 0xFF][] = &$array[$i];
    }

    $i = 0;

    for($slot = 0; $slot < 256; ++ $slot) {
        for($j = 0, $n = count($partition[$slot]); $j < $n; ++ $j) {
            $array[$i ++] = &$partition[$slot][$j];
        }
    }
    return $array;
}

4
@deceze hai coperto tutte le basi .. ho dovuto cercare un altro modo per essere rilevante :)
Baba,

5
Non vedo nulla di sbagliato con i metodi di ordinamento più accademici :) molto meno utili per la maggior parte delle applicazioni, ma a volte possono essere richiesti / richiesti è utile avere un riferimento soprattutto perché mi ero dimenticato della maggior parte di questi nel tempo
Dave

In realtà, per un ordinamento rapido si consiglia di selezionare pivot come mediana di tre valori: primo, medio e ultimo elemento . Questo è il mio esempio per la selezione pivot. Ciò consente di evitare la matrice inversa nel caso peggiore (che provoca O(n^2)confronti se useremo solo il primo elemento come perno)
Alma Do

Ho sentito che spl funziona più velocemente del normale ordinamento di array. È giusto?
Jewelhuq,

Sono d'accordo con Dave, al giorno d'oggi, quasi fw ho incluso questo perché raramente lo ricordo o lo uso.
Mike Nguyen,

43

Ordinamento stabile

Diciamo che hai un array come questo:

['Kale', 'Kaleidoscope', 'Aardvark', 'Apple', 'Leicester', 'Lovely']

E ora vuoi ordinare solo sulla prima lettera:

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

Il risultato è questo:

['Apple', 'Aardvark', 'Kale', 'Kaleidoscope', 'Lovely', 'Leicester']

Il tipo non era stabile!

L'osservatore acuto potrebbe aver notato che l'algoritmo di ordinamento degli array (QuickSort) non ha prodotto un risultato stabile e che l'ordine originale tra le parole della stessa prima lettera non è stato conservato. Questo caso è banale e avremmo dovuto confrontare l'intera stringa, ma supponiamo che il tuo caso d'uso sia più complicato, come due ordinamenti consecutivi su campi diversi che non dovrebbero annullarsi a vicenda.

La trasformata di Schwartz

La trasformata di Schwartz , nota anche come idioma decorare-sminuire, decora un ordinamento stabile con un algoritmo di ordinamento intrinsecamente instabile.

Innanzitutto, decori ogni elemento dell'array con un altro array comprendente una chiave primaria (il valore) e una chiave secondaria (il suo indice o posizione):

array_walk($array, function(&$element, $index) {
    $element = array($element, $index); // decorate
});

Questo trasforma l'array in questo:

[
    ['Kale', 0], ['Kaleidoscope', 1], 
    ['Aardvark', 2], ['Apple', 3], 
    ['Leicester', 4], ['Lovely', 5]
]

Ora, regoliamo il passaggio di confronto; confrontiamo di nuovo la prima lettera, ma se sono uguali, la chiave secondaria viene utilizzata per conservare l'ordine originale:

usort($array, function($a, $b) {
    // $a[0] and $b[0] contain the primary sort key
    // $a[1] and $b[1] contain the secondary sort key
    $tmp = strcmp($a[0][0], $b[0][0]);

    if ($tmp != 0) {
        return $tmp; // use primary key comparison results
    }

    return $a[1] - $b[1]; // use secondary key
});

Successivamente, dichiariamo:

array_walk($array, function(&$element) {
    $element = $element[0];
});

Il risultato finale:

['Aardvark', 'Apple', 'Kale', 'Kaleidoscope', 'Leicester', 'Lovely']

Che dire del riutilizzo?

Dovevi riscrivere la tua funzione di confronto per lavorare con gli elementi dell'array trasformati; potresti non voler modificare le tue delicate funzioni di confronto, quindi ecco un wrapper per la funzione di confronto:

function stablecmp($fn)
{
    return function($a, $b) use ($fn) {
        if (($tmp = call_user_func($fn, $a[0], $b[0])) != 0) {
            return $tmp;
        } else {
            return $a[1] - $b[1];
        }
    };
}

Scriviamo il passaggio di ordinamento usando questa funzione:

usort($array, stablecmp(function($a, $b) {
    return strcmp($a[0], $b[0]);
}));

Ecco! Il tuo codice di confronto originale è tornato.


La tua frase "effettua un ordinamento stabile con un algoritmo di ordinamento intrinsecamente instabile" è stata per me il momento ah-ah. La pagina di Wikipedia non menziona la parola stabile, che mi sembra la bellezza della trasformazione. Vergogna.
Tyler Collier,

1
@TylerCollier Sì, devi leggere tra le righe di quel riferimento di Wikipedia ... Ti ho risparmiato la fatica di farlo ;-)
Ja͢ck

15

A partire da PHP 5.3 con le chiusure è anche possibile utilizzare una chiusura per determinare l'ordine del proprio ordinamento.

Ad esempio, supponendo che $ array sia un array di oggetti che contiene una proprietà mensile.

 $orderArray = array("Jan","Feb","Mar","Apr","May","June","July","Aug","Sept","Oct","Nov","Dec");

 usort($array, function($a, $b) use ($orderArray){
       return array_search($a->month, $orderArray) - array_search($b->month, $orderArray);
 }); 

Ricorda solo che ciò rimuoverà qualsiasi precedente ordine relativo (ad esempio, il primo oggetto "July" nell'elenco preordinato potrebbe finire alla fine del gruppo di oggetti July dopo l'ordinamento). Vedi "Ordinamento stabile" sopra.
George Langley, l'

9

LINQ

In .NET, LINQ viene spesso utilizzato per l'ordinamento, che fornisce una sintassi molto più piacevole rispetto alle funzioni di confronto, soprattutto quando gli oggetti devono essere ordinati per più campi. Esistono diverse porte di LINQ to PHP, inclusa la libreria YaLinqo *. Con esso, le matrici possono essere ordinate con una sola riga senza scrivere complesse funzioni di confronto.

$sortedByName         = from($objects)->orderBy('$v->name');
$sortedByCount        = from($objects)->orderBy('$v->count');
$sortedByCountAndName = from($objects)->orderBy('$v->count')->thenBy('$v->name');

I confronti possono essere ulteriormente personalizzati passando un callback come secondo argomento, ad esempio:

$sortedByFilenameNat  = from($objects)->orderBy('$v->filename', 'strnatcmp');

Qui, '$v->count'è una scorciatoia per function ($v) { return $v->count; }(entrambi possono essere utilizzati). Queste catene di metodi restituiscono iteratori, gli iteratori possono essere trasformati in array aggiungendo ->toArray()alla fine se necessario.

Internamente, orderBye le relative modalità chiamata appropriata funzioni di array di smistamento ( uasort, krsort, multisort, usortecc).

LINQ contiene molti altri metodi ispirati a SQL: filtraggio, raggruppamento, unione, aggregazione ecc. È più adatto per i casi in cui è necessario eseguire trasformazioni complesse su array e oggetti senza fare affidamento su database.

* sviluppato da me, vedere il file Leggimi per maggiori dettagli e il confronto con altre porte LINQ


3

Ordinamento multidimensionale per valore chiave

Ordinamento naturale di un array multidimensionale in base a un valore chiave e anche mantenere l'ordine originale (non mescolare le chiavi principali):

function multisortByKeyValue( $k, $arr ) {
    $ids   = array();
    $index = 1;

    foreach ( $arr as $key => $row ) {
        $ids[ $key ] = intval( $row[ $k ] ) . '-' . $index . '-' . $key;
        $index ++;
    }

    natsort( $ids );

    $arr = array_merge( $ids, $arr );

    return $arr;
}

Caso di prova:

$arr = array(
    'id1' => array(
        'label'    => 'ID 1',
        'priority' => 30,
    ),
    'id2' => array(
        'label'    => 'ID 2',
        'priority' => 70,
    ),
    'id3' => array(
        'label'    => 'ID 3',
        'priority' => 20,
    ),
    'id4' => array(
        'label'    => 'ID 4',
        'priority' => 30,
    ),
);

$sorted = multisortByKeyValue( 'priority', $arr );

// $sorted equals to:
/*
array (
  'id3' => array (
    'label' => 'ID 3',
    'priority' => 20,
  ),
  'id1' => array (
    'label' => 'ID 1',
    'priority' => 30,
  ),
  'id4' => array (
    'label' => 'ID 4',
    'priority' => 30,
  ),
  'id2' => array (
    'label' => 'ID 2',
    'priority' => 70,
  ),
)
*/

2

È molto conveniente ordinare le matrici con la funzione ordinata da Nspl :

Ordinamento di base

// Sort array
$sorted = sorted([3, 1, 2]);

// Sort array in descending order
$sortedDesc = sorted([3, 1, 2], true);

Ordinamento per risultato della funzione

// Sort array by the result of a given function (order words by length)
$sortedByLength = sorted(['bc', 'a', 'abc'], 'strlen');
$sortedByLengthDesc = sorted(['bc', 'a', 'abc'], true, 'strlen');

// Sort array by the result of user-defined function (order words by the 1st character)
$sortedByTheFirstCharacter = sorted(['bc', 'a', 'abc'], function($v) { return $v[0]; }); 

// Which is the same as
$sortedByTheFirstCharacter = sorted(['bc', 'a', 'abc'], itemGetter(0));
$sortedByTheFirstCharacterDesc = sorted(['bc', 'a', 'abc'], true, itemGetter(0));

// itemGetter(0) returns a function which takes an argument with access by index/key
// and returns the value at index 0

Ordinamento di array multidimensionali

// Sort multidimensional array (sort list of users by their names)
$users = [
    array('name' => 'Robert', 'age' => 20),
    array('name' => 'Alex', 'age' => 30),
    array('name' => 'Jack', 'age' => 25),
];
$sortedByName = sorted($users, itemGetter('name'));
$sortedByNameDesc = sorted($users, true, itemGetter('name'));

// itemGetter('name') returns a function which takes an argument with access by index/key
// and returns the value of the 'name' key

Ordinamento di array di oggetti

// Lets assume we have class User(name, age) with properties name and age
// and public methods getName() and getAge()
$users = [
    new User('Robert', 20),
    new User('Alex', 30),
    new User('Jack', 25),
];

// Sort list of objects by property value (sort list of users by their name)
$sortedByName = sorted($users, propertyGetter('name'));
$sortedByNameDesc = sorted($users, true, propertyGetter('name'));

// propertyGetter('name') returns a function which takes an object
// and returns the value of its 'name' property

// Sort list of objects by method result (sort list of users by their age)
$sortedByAge = sorted($users, methodCaller('getAge'));
$sortedByAgeDesc = sorted($users, true, methodCaller('getAge'));

// methodCaller('getAge') returns a function which takes an object
// and returns the result of its getAge() method

Ordinamento con una funzione di confronto

// Sort with a comparison function (order words lexicographically with strcmp)
$sortedLexicographically = sorted(['bc', 'a', 'abc'], false, null, 'strcmp');

// Sort with user-defined comparison function (order words by the 1st character)
$sortedByTheFirstCharacter = sorted(['bc', 'a', 'abc'], false, null, function($v1, $v2) {
    return chr($v1[0]) - chr($v2[0]);
});

Puoi vedere tutti questi esempi qui .


2

Se vuoi ordinare in base al valore chiave, puoi farlo in una riga, elegante e chiaro. Questo ordinerà per il prezzo crescente. Utilizza array_multisort e array_column.

   Array([0] => Array ( [name] => eggs [price] => 1 ) [1] => Array ( [name] => coffee [price] => 9.99 ) [2] => Array ( [name] => rice [price] => 4.04 ) )

   array_multisort (array_column($array, 'price'), SORT_ASC, $array);

produrre

     Array ( [0] => Array ( [name] => eggs [price] => 1 ) [1] => Array ( [name] => rice [price] => 4.04 ) [2] => Array ( [name] => coffee [price] => 9.99 ) )

1

Questa pagina è molto completa, ma voglio aggiungere un po 'di più sulla straordinaria utility dell'operatore dell'astronave (operatore di confronto a tre vie) - un bellissimo bambino di PHP7 +.

Utilizzo dell'operatore dell'astronave per implementare più condizioni di ordinamento

Questo fa passi da gigante nel ridurre il gonfiore del codice e nel migliorare la leggibilità.

Quando si scrive la funzione di ordinamento personalizzata ( usort()/ uasort()/ uksort()) per elaborare più condizioni, è necessario solo scrivere array bilanciati su entrambi i lati dell'operatore e restituire il risultato. Niente più blocchi condizionali nidificati o più ritorni.

Gli elementi da entrambi i lati dell'operatore verranno attraversati da sinistra a destra, uno alla volta, e restituiranno la valutazione non appena si incontra un non-tie o quando gli elementi sono stati confrontati.

Dati di esempio per le mie dimostrazioni:

$multidimArray = [
    'a' => [
        'boolean' => true,
        'natString' => 'text10',
        'object' => (object)['prop' => 2],
        'float' => -.5,
        'mixed' => []
    ],
    'b' => [
        'boolean' => true,
        'natString' => 'text12',
        'object' => (object)['prop' => 4],
        'float' => 0,
        'mixed' => null
    ],
    'c' => [
        'boolean' => false,
        'natString' => 'text100',
        'object' => (object)['prop' => 9],
        'float' => -.5,
        'mixed' => false
    ],
    'd' => [
        'boolean' => true,
        'natString' => 'text1',
        'object' => (object)['prop' => 9],
        'float' => -5,
        'mixed' => "\0"
    ],
    'e' => [
        'boolean' => false,
        'natString' => 'text2',
        'object' => (object)['prop' => 2],
        'float' => .5,
        'mixed' => ''
    ]
];

Dimostrazioni (per evitare il gonfiamento della pagina StackOverflow, consultare il collegamento demo per gli output):

  • Logica di ordinamento:

    1. booleano DESC (false = 0, true = 1, quindi veri prima dei falsi)
    2. float ASC

      uasort($multidimArray, function($a, $b) {
          return [$b['boolean'], $a['float']] <=> [$a['boolean'], $b['float']];
      });
  • Logica di ordinamento:

    1. ASC misto
    2. oggetto ASC
    3. ASC booleano

      uasort($multidimArray, function($a, $b) {
          return [$a['mixed'], $a['object']->prop, $a['boolean']] <=> [$b['mixed'], $b['object']->prop, $b['boolean']];
      });
  • Logica di ordinamento:

    1. conteggio proprietà dell'oggetto ASC
    2. iterabilità di DESC misto
    3. natString lunghezza ASC
    4. natString ASC

      uasort($multidimArray, function($a, $b) {
          return [count(get_object_vars($a['object'])), is_iterable($a['mixed']), strlen($a['natString']), $a['natString']]
                 <=>
                 [count(get_object_vars($b['object'])), is_iterable($b['mixed']), strlen($b['natString']), $b['natString']];
      });

Questa sintassi consente di ordinare i valori, i risultati funzionali, i dati approfonditi e la direzione di ordinamento in modo elegante. Vale sicuramente la pena inserire la cintura degli strumenti di php ... per i casi in cui si stanno elaborando dati non di database - perché ovviamente SQL sarebbe una tecnica molto più sensata.

A tua discrezione, da PHP7.4 puoi usare la sintassi della freccia con queste funzioni anonime. Stesso script con sintassi della freccia .


0

Se qualcuno desidera una soluzione più semplice per manipolare le matrici, basta usare il pacchetto Laravel Collection che ha una funzione sortBy implementata che consente semplicemente l'ordinamento per chiavi.

$collection->sortBy('forename')->sortBy('surname');

vale a dire, per ordinare prima per a, poi b, quindi c, la clausola corretta sarebbe

sortBy('c')->sortBy('b')->sortBy('a')

https://packagist.org/packages/tightenco/collect


-1

Esistono diversi modi per ordinare un array. Citerò alcuni metodi per svolgere tale compito. Prima di tutto, darò un array intero che si chiama '$ numbers'.

$number = array(8,9,3,4,0,1,2);

Questo è il modo normale di creare un array. Supponiamo che io voglia ordinare quell'array in ordine crescente, per cui è possibile utilizzare il metodo 'sort ()'.

<?php

    $number = array(8,9,3,4,0,1,2);
    sort($number);

   foreach ($number as $value) {
       echo $value."  ";
   }
?>

Ora considera l'output di quello,

inserisci qui la descrizione dell'immagine

È possibile visualizzare la matrice dei numeri stampati ordinata. Se si desidera che l'array numerico da ordinare sia in ordine decrescente, è possibile utilizzare il metodo 'rsort ()' per tale attività.

<?php

     $number = array(8,9,3,4,0,1,2);
     rsort($number);

     foreach ($number as $value) {
        echo $value."  ";
     }
?>

considerare l'output ..

inserisci qui la descrizione dell'immagine

Ora l'array è ordinato in ordine decrescente. Ok, consideriamo un array associativo. Darò un array associativo (array associativo significa che, un array il cui ogni indice ha un valore chiave univoco.) Come questo,

$number = array('eight'=>8,'nine'=>9,'three'=>3,'fore'=>4,'zero'=>0,'one'=>1,'two'=>2);

Quindi, ora voglio ordinare questo array in ordine crescente secondo il loro valore. Il metodo 'asort ()' può essere usato per quello.

<?php

   $number = array('eight'=>8,'nine'=>9,'three'=>3,'fore'=>4,'zero'=>0,'one'=>1,'two'=>2);
   asort($number);

   foreach ($number as $value) {
      echo $value."  ";
    }
?>

Se si ordina in ordine decrescente in base al loro valore, è possibile utilizzare il metodo 'arsort ()'. Supponiamo di voler ordinare quell'array in base al loro valore chiave. In questo, può essere usato il metodo 'ksort ()'.

<?php

     $number = array('eight'=>8,'nine'=>9,'three'=>3,'fore'=>4,'zero'=>0,'one'=>1,'two'=>2);
     ksort($number);

     foreach ($number as $value) {
         echo $value."  ";
     }
?>

Ora considera l'output. inserisci qui la descrizione dell'immagine

Ora l'array viene ordinato in base al valore della chiave. Se si desidera ordinare l'array in ordine decrescente in base al valore della chiave, è possibile utilizzare il metodo 'krsort ()'.

<?php

    $number = array('eight'=>8,'nine'=>9,'three'=>3,'fore'=>4,'zero'=>0,'one'=>1,'two'=>2);
    krsort($number);

    foreach ($number as $value) {
       echo $value."  ";
    }
?>

Ora la matrice associativa è ordinata in ordine decrescente secondo il loro valore chiave. Guarda l'output. inserisci qui la descrizione dell'immagine

Questi sono alcuni metodi per ordinare un array in ordine crescente o decrescente in php. Spero che tu possa avere un'idea. Grazie!


Deceze non copre già queste intuizioni con: "La differenza tra queste è semplicemente se le associazioni di valori-chiave vengono mantenute (le funzioni" a "), se ordinano dal basso all'alto o al contrario (" r "), indipendentemente dal fatto che ordina i valori o le chiavi ("k") e il modo in cui confronta i valori ("nat" vs. normale). " nella risposta accettata?
Mickmackusa,

-2

Il più semplice è utilizzare la funzione usort per ordinare l'array senza alcun ciclo: di seguito è riportato un esempio:

   $array_compare= array("0" =>4,"1"=>2,"2"=>500,"3"=>100);

Questo ordinerà nell'ordine desiderato:

usort($array_compare, function($a, $b) {
        return ($b['x1'] - $a['x1']) > 0 ? 1 :-1;
    });

Questo ordinerà in ordine crescente:

usort($array_compare, function($a, $b) {
        return ($b['x1'] - $a['x1']) < 0 ? 1 :-1;
    });

1
1) L'esempio e il codice sono incoerenti. 2) Questo è già spiegato in modo estremamente dettagliato nelle risposte sopra. 3) Stai forse cercando di rispondere a una domanda diversa?
Inganno
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.