Bagaimana saya bisa mengurutkan array dan data dalam PHP?

292

Pertanyaan ini dimaksudkan sebagai referensi untuk pertanyaan tentang menyortir array dalam PHP. Mudah untuk berpikir bahwa kasus khusus Anda unik dan layak untuk sebuah pertanyaan baru, tetapi sebagian besar sebenarnya merupakan variasi kecil dari salah satu solusi di halaman ini.

Jika pertanyaan Anda ditutup sebagai duplikat dari pertanyaan ini, harap minta pertanyaan Anda dibuka kembali hanya jika Anda dapat menjelaskan mengapa pertanyaan itu sangat berbeda dari semua yang di bawah ini.

Bagaimana cara saya mengurutkan array dalam PHP?
Bagaimana cara saya mengurutkan array yang rumit di PHP?
Bagaimana cara saya mengurutkan array objek di PHP?


  1. Array satu dimensi dasar; Termasuk Array multidimensi, termasuk. array benda; Termasuk Mengurutkan satu array berdasarkan yang lain

  2. Mengurutkan dengan SPL

  3. Semacam stabil

Untuk jawaban praktis menggunakan fungsi PHP yang ada, lihat 1., untuk jawaban mendetail akademik tentang algoritme pengurutan (fungsi PHP yang diterapkan dan yang mungkin Anda perlukan untuk kasus yang benar-benar rumit), lihat 2.

tipuan
sumber
@ jterry Persis, itu sebabnya saya membuat ini untuk akhirnya memiliki pertanyaan referensi yang bagus untuk ditutup. Menjawab setiap kepingan salju yang unik secara individual tidak membantu siapa pun. :)
deceze
3
Saya pikir orang harus melihat php.net
Alexander Jardim
@ Alex Ha! Benar. Masalahnya adalah: tidak ada RTFM. : D
deceze
2
Kami sudah memiliki jawaban-jawaban itu, saya sarankan Anda daftar-tautkan jawaban terbaik di dalam setiap jawaban di sini daripada menduplikasi (atau menulis ulang) konten. Array juga cenderung terlihat secara individual sehingga pekerjaan tetap menutup suara terhadap dupes dalam hal apapun.
hakre
1
@menerima: Jika tidak ada RTFM, tidak ada yang juga akan RTFQA - T&J yang ada :)
hakre

Jawaban:

164

Array satu dimensi dasar

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

Fungsi pengurutan yang berlaku:

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

Perbedaan antara keduanya hanyalah apakah asosiasi nilai kunci dipertahankan (" a" fungsi), apakah itu mengurutkan rendah ke tinggi atau terbalik (" r"), apakah itu mengurutkan nilai atau kunci (" k") dan bagaimana ia membandingkan nilai-nilai (" nat" vs normal). Lihat http://php.net/manual/en/array.sorting.php untuk ikhtisar dan tautan ke detail lebih lanjut.

Array multi dimensi, termasuk array benda

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

Jika Anda ingin mengurutkan $arrayberdasarkan 'foo' kunci dari setiap entri, Anda memerlukan fungsi perbandingan khusus . sortFungsi-fungsi di atas dan terkait bekerja pada nilai-nilai sederhana yang mereka tahu bagaimana membandingkan dan mengurutkan. PHP tidak hanya "tahu" apa yang harus dilakukan dengan nilai kompleks seperti array('foo' => 'bar', 'baz' => 42); jadi kamu harus mengatakannya.

Untuk melakukan itu, Anda perlu membuat fungsi perbandingan . Fungsi itu mengambil dua elemen dan harus kembali 0jika elemen-elemen ini dianggap sama, nilai lebih rendah dari 0jika nilai pertama lebih rendah dan nilai lebih tinggi daripada 0jika nilai pertama lebih tinggi. Hanya itu yang dibutuhkan:

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

Seringkali, Anda ingin menggunakan fungsi anonim sebagai panggilan balik. Jika Anda ingin menggunakan metode atau metode statis, lihat cara lain untuk menentukan panggilan balik dalam PHP .

Anda kemudian menggunakan salah satu dari fungsi-fungsi ini:

Sekali lagi, mereka hanya berbeda dalam apakah mereka menyimpan asosiasi nilai kunci dan mengurutkan berdasarkan nilai atau kunci. Baca dokumentasi mereka untuk detailnya.

Contoh penggunaan:

usort($array, 'cmp');

usortakan mengambil dua item dari array dan memanggil cmpfungsi Anda dengannya. Jadi cmp()akan dipanggil dengan $asebagai array('foo' => 'bar', 'baz' => 42)dan $bsebagai yang lain array('foo' => ..., 'baz' => ...). Fungsi kemudian kembali ke usortnilai mana yang lebih besar atau apakah mereka sama. usortmengulangi proses ini melewati nilai yang berbeda untuk $adan $bsampai array diurutkan. The cmpfungsi akan dipanggil berkali-kali, setidaknya sebanyak yang ada nilai-nilai dalam $array, dengan kombinasi yang berbeda dari nilai-nilai untuk $adan $bsetiap waktu.

Untuk terbiasa dengan ide ini, coba ini:

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

Yang Anda lakukan hanyalah menentukan cara kustom untuk membandingkan dua item, hanya itu yang Anda butuhkan. Itu bekerja dengan segala macam nilai.

By the way, ini bekerja pada nilai apa pun, nilai tidak harus menjadi array yang kompleks. Jika Anda memiliki perbandingan ubahsuaian yang ingin Anda lakukan, Anda juga dapat melakukannya pada array angka sederhana.

sort macam dengan referensi dan tidak mengembalikan apa pun yang berguna!

Perhatikan bahwa array ada di tempat , Anda tidak perlu menetapkan nilai kembali untuk apa pun. $array = sort($array)akan mengganti array dengan true, bukan dengan array yang diurutkan. Hanya sort($array);bekerja.

Perbandingan angka khusus

Jika Anda ingin mengurutkan berdasarkan bazkunci, yang berupa angka, yang perlu Anda lakukan adalah:

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

Berkat The PoWEr of MATH ini mengembalikan nilai <0, 0 atau> 0 tergantung pada apakah $alebih rendah dari, sama dengan atau lebih besar dari $b.

Perhatikan bahwa ini tidak akan berfungsi dengan baik untuk floatnilai, karena nilai tersebut akan dikurangi menjadi intdan kehilangan presisi. Gunakan eksplisit -1, 0dan 1kembalikan nilai.

Benda

Jika Anda memiliki array objek, ia bekerja dengan cara yang sama:

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

Fungsi

Anda dapat melakukan apa pun yang Anda butuhkan di dalam fungsi perbandingan, termasuk fungsi panggilan:

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

String

Pintasan untuk versi perbandingan string pertama:

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

strcmptidak persis apa yang diharapkan dari cmpsini, mengembalikan -1, 0atau 1.

Operator pesawat ruang angkasa

PHP 7 memperkenalkan operator pesawat ruang angkasa , yang menyatukan dan menyederhanakan sama / lebih kecil / lebih besar dari perbandingan antar jenis:

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

Menyortir berdasarkan beberapa bidang

Jika Anda ingin mengurutkan berdasarkan foo, tetapi jika foosama untuk dua elemen, urutkan berdasarkan baz:

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

Bagi yang terbiasa, ini setara dengan permintaan SQL dengan ORDER BY foo, baz.
Juga lihat versi steno yang sangat rapi ini dan cara membuat fungsi pembanding secara dinamis untuk sejumlah kunci yang berubah-ubah .

Menyortir ke dalam urutan manual, statis

Jika Anda ingin mengurutkan elemen menjadi "urutan manual" seperti "foo", "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);
}

Untuk semua hal di atas, jika Anda menggunakan PHP 5.3 atau lebih tinggi (dan memang harus demikian), gunakan fungsi anonim untuk kode yang lebih pendek dan untuk menghindari ada fungsi global lain yang beredar:

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

Begitulah cara sederhana menyortir array multi dimensi yang kompleks. Sekali lagi, pikirkan saja dalam hal mengajar PHP bagaimana cara membedakan mana dari dua item yang "lebih besar" ; biarkan PHP melakukan penyortiran yang sebenarnya.

Juga untuk semua hal di atas, untuk beralih antara urutan naik dan turun cukup menukar $adan $bargumen di sekitar. Misalnya:

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

Mengurutkan satu array berdasarkan yang lain

Dan kemudian ada yang aneh array_multisort, yang memungkinkan Anda mengurutkan satu array berdasarkan yang lain:

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

Hasil yang diharapkan di sini adalah:

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

Gunakan array_multisortuntuk sampai ke sana:

array_multisort($array1, $array2);

Pada PHP 5.5.0 Anda dapat menggunakan array_columnuntuk mengekstrak kolom dari array multi dimensi dan mengurutkan array pada kolom itu:

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

Pada PHP 7.0.0 Anda juga dapat mengekstrak properti dari berbagai objek.


Jika Anda memiliki kasus yang lebih umum, silakan edit jawaban ini.

tipuan
sumber
Fungsi perbandingan numerik tidak berfungsi untuk nilai float; Saya yakin Anda tahu apa yang saya maksud :)
Ja͢ck
1
Untuk urutan statis, saya akan menerapkan array_flip()untuk menggunakan pencarian posisi lebih cepat, misalnya $order[$a['foo']]bukan array_search($a['foo'], $order).
Ja͢ck
Mungkin ada sedikit pengeditan besar: gist.github.com/Rizier123/24a6248758b53245a63e839d8e08a32b tetapi jika Anda pikir ini merupakan peningkatan dan saya menyertakan semua yang penting saya bisa menerapkannya.
Rizier123
@ Rizier123 Saya tentu saja memuji usaha ini, ini merupakan langganan yang sangat bagus; tapi saya lebih suka jika Anda mempostingnya sebagai jawaban terpisah, meskipun sangat mirip. Penulisan ulang Anda mengandung banyak detail (lewat referensi, tabel besar, dll.), Tetapi detail itu mengalihkan perhatian dari pengantar yang halus ke topik inti dari cara kerja fungsi perbandingan, IMHO. Saya secara eksplisit merujuk pada manual beberapa kali dengan sengaja, karena di situlah detail seperti itu harus dicari; tidak perlu mengulanginya di sini dan mengalihkan perhatian dari ide inti yang saya coba sampaikan.
tipuan
@menerima Tantangan utama, karena ini adalah Q&A referensi, adalah untuk menampilkan informasi yang ringkas dan mudah dibaca serta memudahkan pengguna untuk menemukan fungsi penyortiran mereka. Saya mengubah beberapa hal: gist.github.com/Rizier123/24a6248758b53245a63e839d8e08a32b tapi saya masih harus memikirkannya, apakah berguna dan berharga untuk mempostingnya sebagai jawaban terpisah, karena kontennya sangat mirip
Rizier123
139

Yah sebagian besar metode dasar sudah tercakup oleh tipuan saya akan mencoba untuk melihat jenis penyortiran lainnya

Mengurutkan dengan 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));

Keluaran

c
b
a

SplMaxHeap

Kelas SplMaxHeap menyediakan fungsi utama heap, menjaga maksimum di atas.

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

SplMinHeap

Kelas SplMinHeap menyediakan fungsi utama tumpukan, menjaga minimum di atas.

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

Jenis Penyortiran Lainnya

Sortir Bubble

Dari artikel Wikipedia tentang Bubble Sort:

Bubble sort, kadang-kadang secara tidak tepat disebut sebagai sinking sort, adalah algoritma penyortiran sederhana yang bekerja dengan berulang kali menelusuri daftar yang akan diurutkan, membandingkan setiap pasangan item yang berdekatan dan menukarnya jika item tersebut berada dalam urutan yang salah. Lewat daftar diulangi sampai tidak ada swap yang diperlukan, yang menunjukkan bahwa daftar diurutkan. Algoritma mendapatkan namanya dari cara elemen yang lebih kecil "gelembung" ke bagian atas daftar. Karena hanya menggunakan perbandingan untuk beroperasi pada elemen, itu adalah semacam perbandingan. Meskipun algoritmanya sederhana, sebagian besar algoritma pengurutan lainnya lebih efisien untuk daftar besar.

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;
}

Sortir seleksi

Dari artikel Wikipedia tentang Seleksi:

Dalam ilmu komputer, pemilihan semacam adalah algoritma pengurutan, khususnya jenis perbandingan di tempat. Ini memiliki kompleksitas waktu O (n2), membuatnya tidak efisien pada daftar besar, dan umumnya berkinerja lebih buruk daripada jenis penyisipan yang sama. Sortir pemilihan dicatat karena kesederhanaannya, dan memiliki keunggulan kinerja dibandingkan algoritma yang lebih rumit dalam situasi tertentu, terutama di mana memori tambahan terbatas.

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;
}

Jenis penyisipan

Dari artikel Wikipedia tentang penyisipan:

Sortasi penyisipan adalah algoritme pengurutan sederhana yang membangun array (atau daftar) akhir yang diurutkan satu per satu. Ini jauh lebih efisien pada daftar besar daripada algoritma yang lebih maju seperti quicksort, heapsort, atau semacam penggabungan. Namun, penyisipan memberikan beberapa keuntungan:

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

Dari artikel Wikipedia tentang Shellsort:

Shellsort, juga dikenal sebagai jenis Shell atau metode Shell, adalah jenis perbandingan di tempat. Ini menggeneralisasi jenis pertukaran, seperti penyisipan atau jenis gelembung, dengan memulai perbandingan dan pertukaran elemen dengan elemen yang berjauhan sebelum selesai dengan elemen tetangga.

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;
}

Semacam sisir

Dari artikel Wikipedia tentang jenis Sisir:

Comb sort adalah algoritma pengurutan yang relatif sederhana yang awalnya dirancang oleh Wlodzimierz Dobosiewicz pada 1980. Kemudian ditemukan kembali oleh Stephen Lacey dan Richard Box pada 1991. Comb sort ditingkatkan pada bubble sort.

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;
}

Gabungkan semacam

Dari artikel Wikipedia di Gabung urut:

Dalam ilmu komputer, semacam gabungan (juga biasanya dieja mergesort) adalah algoritma sortir berbasis perbandingan O (n log n). Sebagian besar implementasi menghasilkan semacam stabil, yang berarti bahwa implementasi mempertahankan urutan input elemen yang sama dalam output yang diurutkan

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

Dari artikel Wikipedia di Quicksort:

Quicksort, atau sortir pertukaran pertukaran, adalah algoritma penyortiran yang dikembangkan oleh Tony Hoare yang, rata-rata, membuat perbandingan O (n log n) untuk mengurutkan n item. Dalam kasus terburuk, itu membuat perbandingan O (n2), meskipun perilaku ini jarang terjadi.

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

Jenis permutasi

Dari artikel Wikipedia tentang jenis Permutasi:

Sortasi permutasi, yang menghasilkan dengan menghasilkan permutasi yang mungkin dari array input / daftar sampai menemukan yang diurutkan.

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;
}

Jenis radix

Dari artikel Wikipedia tentang Radix sort:

Dalam ilmu komputer, radix sort adalah algoritma pengurutan integer non-komparatif yang mengurutkan data dengan kunci integer dengan mengelompokkan kunci berdasarkan masing-masing digit yang memiliki posisi dan nilai signifikan yang sama.

// 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;
}
Baba
sumber
4
@menerima Anda membahas semua hal mendasar .. saya harus mencari cara lain agar relevan :)
Baba
5
Saya tidak melihat ada yang salah dengan metode penyortiran yang lebih akademis :) banyak yang kurang berguna untuk sebagian besar aplikasi tetapi kadang-kadang mereka diminta / diminta berguna untuk memiliki referensi terutama karena saya akan lupa tentang sebagian besar dari ini dari waktu ke waktu
Dave
Sebenarnya, untuk pengurutan cepat, disarankan untuk memilih pivot sebagai median tiga nilai: elemen pertama, tengah dan terakhir . Ini adalah contoh saya untuk seleksi pivot. Itu memungkinkan untuk menghindari array yang diurutkan terbalik dengan kasus terburuk (yang menyebabkan O(n^2)perbandingan jika kita akan menggunakan elemen pertama sebagai pivot)
Alma Do
Saya telah mendengar bahwa spl bekerja lebih cepat daripada penyortiran array normal. Apakah itu benar?
jewelhuq
Saya setuju dengan Dave, saat ini, hampir semuanya memasukkan mengapa saya jarang mengingat atau menggunakannya.
Mike Nguyen
43

Semacam stabil

Katakanlah Anda memiliki array seperti ini:

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

Dan sekarang Anda ingin mengurutkan hanya pada huruf pertama:

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

Hasilnya adalah ini:

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

Semacam itu tidak stabil!

Pengamat yang tajam mungkin telah memperhatikan bahwa algoritma pengurutan array (QuickSort) tidak menghasilkan hasil yang stabil dan bahwa urutan asli antara kata-kata dari huruf pertama yang sama tidak dipertahankan. Kasing ini sepele dan kami harus membandingkan seluruh string, tetapi anggap saja kasing Anda lebih rumit, seperti dua jenis berturut-turut pada bidang berbeda yang tidak boleh membatalkan pekerjaan masing-masing.

Transformasi Schwartzian

Transformasi Schwartzian , juga disebut sebagai idiom menghias-sort-undecorate, memberikan efek jenis stabil dengan algoritma penyortiran yang secara inheren tidak stabil.

Pertama, Anda menghias setiap elemen array dengan array lain yang terdiri dari kunci primer (nilai) dan kunci sekunder (indeks atau posisinya):

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

Ini mengubah array menjadi ini:

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

Sekarang, kami menyesuaikan langkah perbandingan; kami membandingkan huruf pertama lagi, tetapi jika itu sama, kunci sekunder digunakan untuk mempertahankan pemesanan asli:

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

Setelah itu, kami membatalkan dekorasinya:

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

Hasil akhir:

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

Bagaimana dengan penggunaan kembali?

Anda harus menulis ulang fungsi perbandingan untuk bekerja dengan elemen array yang diubah; Anda mungkin tidak ingin mengedit fungsi perbandingan halus Anda, jadi inilah bungkus untuk fungsi perbandingan:

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];
        }
    };
}

Mari kita menulis langkah penyortiran menggunakan fungsi ini:

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

Voila! Kode perbandingan asli Anda kembali.

Mendongkrak
sumber
Frasa Anda "memengaruhi pengurutan stabil dengan algoritme pengurutan yang secara inheren tidak stabil" adalah momen ah-ha bagi saya. Halaman wikipedia tidak menyebutkan kata stable, yang menurut saya adalah keindahan dari transformasi. Malu.
Tyler Collier
1
@TylerCollier Ya, Anda perlu membaca antara garis-garis yang referensi Wikipedia ... Aku menyelamatkan Anda kesulitan melakukan itu ;-)
Jack
15

Pada PHP 5.3 dengan penutupan juga dimungkinkan untuk menggunakan penutupan untuk menentukan urutan jenis Anda.

Misalnya dengan asumsi $ array adalah array objek yang berisi properti bulan.

 $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);
 }); 
Orangepill
sumber
Ingatlah bahwa ini akan menghapus urutan relatif sebelumnya (misalnya, objek "Juli" pertama dalam daftar yang disortir mungkin berakhir pada akhir grup objek Juli setelah pengurutan). Lihat "Sortasi Stabil" di atas.
George Langley
9

LINQ

Dalam .NET, LINQ sering digunakan untuk menyortir, yang menyediakan sintaks yang jauh lebih baik daripada fungsi perbandingan, terutama ketika objek perlu diurutkan berdasarkan beberapa bidang. Sudah ada beberapa port LINQ ke PHP, termasuk perpustakaan YaLinqo *. Dengan itu, array dapat diurutkan dengan satu baris tanpa menulis fungsi perbandingan yang kompleks.

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

Perbandingan dapat dikustomisasi lebih lanjut dengan meneruskan panggilan balik sebagai argumen kedua, misalnya:

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

Di sini, '$v->count'adalah singkatan untuk function ($v) { return $v->count; }(keduanya dapat digunakan). Rantai metode ini mengembalikan iterator, iterator dapat diubah menjadi array dengan menambahkan ->toArray()pada akhirnya jika diperlukan.

Internal, orderBydan metode terkait memanggil berbagai pemilahan fungsi yang sesuai ( uasort, krsort, multisort, usortdll).

LINQ berisi lebih banyak metode yang terinspirasi oleh SQL: pemfilteran, pengelompokan, penggabungan, penjumlahan, dll. Ini paling cocok untuk kasus-kasus ketika transformasi kompleks pada array dan objek perlu dilakukan tanpa bergantung pada database.

* Dikembangkan oleh saya, lihat readme untuk detail lebih lanjut dan perbandingan dengan port LINQ lainnya

Athari
sumber
3

Urutkan multidimensi berdasarkan nilai kunci

Semacam alami array multidimensi dengan nilai kunci dan juga menjaga urutan asli (jangan mengocok kunci utama):

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;
}

Kasus cobaan:

$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,
  ),
)
*/
Andrew Surdu
sumber
2

Sangat mudah untuk mengurutkan array dengan fungsi yang diurutkan dari Nspl :

Penyortiran dasar

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

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

Mengurutkan berdasarkan hasil fungsi

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

Mengurutkan array multidimensi

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

Menyortir berbagai objek

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

Menyortir dengan fungsi perbandingan

// 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]);
});

Anda dapat melihat semua contoh ini di sini .

Ihor Burlachenko
sumber
2

Jika Anda ingin memesan berdasarkan nilai kunci, maka Anda dapat melakukannya satu baris, elegan dan jelas. Ini akan dipesan dengan harga naik. Menggunakan array_multisort dan 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);

untuk menghasilkan

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

Halaman ini sangat komprehensif, tetapi saya ingin menambahkan sedikit lebih banyak tentang utilitas luar biasa dari operator pesawat ruang angkasa (operator perbandingan tiga arah) - anak yang cantik dari PHP7 +.

Menggunakan operator pesawat ruang angkasa untuk menerapkan beberapa kondisi penyortiran

Ini membuat langkah besar dalam mengurangi mengasapi kode dan meningkatkan keterbacaan.

Saat menulis fungsi penyortiran khusus Anda ( usort()/ uasort()/ uksort()) untuk memproses beberapa kondisi, Anda hanya perlu menulis array yang seimbang di kedua sisi operator dan mengembalikan hasilnya. Tidak ada lagi blok kondisi bersarang atau beberapa pengembalian.

Elemen-elemen dari kedua sisi operator akan dilintasi dari kiri ke kanan, satu per satu, dan mengembalikan evaluasi segera setelah tidak ada ikatan atau ketika semua elemen telah dibandingkan.

Sampel data untuk demonstrasi saya:

$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' => ''
    ]
];

Demonstrasi (untuk menghindari kembungnya halaman Stackoverflow, silakan lihat tautan demo untuk hasilnya):

  • Logika penyortiran:

    1. boolean DESC (false = 0, true = 1, jadi trues sebelum falses)
    2. mengapung ASC

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

    1. campuran ASC
    2. objek ASC
    3. boolean ASC

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

    1. hitungan properti objek ASC
    2. iterability DESC campuran
    3. natString panjang 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']];
      });

Sintaks ini memungkinkan Anda untuk mengurutkan nilai, hasil fungsional, data yang bersarang mendalam, dan arah penyortiran secara elegan. Ini jelas layak untuk dimasukkan ke dalam toolbelt php Anda ... untuk kasus-kasus ketika Anda memproses data non-basis data - karena tentu saja SQL akan menjadi teknik yang jauh lebih masuk akal.

Atas kebijakan Anda sendiri, dari PHP7.4 Anda dapat menggunakan sintaks panah dengan fungsi-fungsi anonim ini. Script yang sama dengan sintaks panah .

mickmackusa
sumber
0

Jika seseorang menginginkan solusi yang lebih sederhana untuk memanipulasi array, cukup gunakan paket Laravel Collection yang memiliki fungsi sortBy yang diimplementasikan yang memungkinkan Anda mengurutkan berdasarkan kunci dengan mudah.

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

yaitu, untuk mengurutkan pertama dengan a, lalu b, lalu c, klausa yang benar adalah

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

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

Rizerzero
sumber
-1

Ada beberapa cara untuk mengurutkan array. Saya akan menyebutkan beberapa metode untuk melakukan tugas itu. Pertama-tama, saya akan memberikan array integer yang disebut sebagai '$ number'.

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

Ini adalah cara normal untuk membuat array. Misalkan, saya ingin mengurutkan array dalam urutan menaik. Untuk itu, metode 'sort ()' dapat digunakan.

<?php

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

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

Sekarang perhatikan output dari itu,

masukkan deskripsi gambar di sini

Anda dapat melihat array angka yang dicetak diurutkan. Jika Anda ingin agar array angka menjadi semacam adalah urutan menurun, metode 'rsort ()' dapat digunakan untuk tugas itu.

<?php

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

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

pertimbangkan output ..

masukkan deskripsi gambar di sini

Sekarang array diurutkan dalam urutan menurun. Oke, Mari kita pertimbangkan array asosiatif. Saya akan memberikan array asosiatif (array Asosiatif berarti bahwa, sebuah array yang setiap indeksnya memiliki nilai kunci unik.) Seperti ini,

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

Jadi, Sekarang saya ingin mengurutkan array ini dalam urutan menaik menurut nilainya. Metode 'asort ()' dapat digunakan untuk itu.

<?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."  ";
    }
?>

Jika mengurutkan pesanan menurun sesuai nilainya, metode 'arsort ()' dapat digunakan. Misalkan Anda ingin mengurutkan array berdasarkan nilai kunci mereka. Dalam hal ini, metode 'ksort ()' dapat digunakan.

<?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."  ";
     }
?>

Sekarang perhatikan hasilnya. masukkan deskripsi gambar di sini

Sekarang array diurutkan berdasarkan nilai kunci mereka. Jika Anda ingin mengurutkan array dalam urutan menurun sesuai dengan nilai kunci mereka, metode 'krsort ()' dapat digunakan.

<?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."  ";
    }
?>

Sekarang array asosiatif diurutkan dalam urutan menurut nilai kunci mereka. Lihatlah output. masukkan deskripsi gambar di sini

Ini adalah beberapa metode untuk menyortir array dalam urutan naik atau turun di php. Saya harap Anda bisa mendapatkan ide. Terima kasih!

GT_hash
sumber
Bukankah Deceze sudah mencakup wawasan ini dengan: "Perbedaan di antara mereka hanyalah apakah asosiasi nilai kunci dipertahankan (" a "berfungsi), apakah itu mengurutkan rendah ke tinggi atau terbalik (" r "), apakah itu mengurutkan nilai atau kunci ("k") dan bagaimana membandingkan nilai ("nat" vs normal). " dalam jawaban yang diterima?
mickmackusa
-2

Yang paling sederhana adalah menggunakan fungsi usort untuk mengurutkan array tanpa pengulangan: Di bawah ini adalah contoh:

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

Ini akan mengurutkan dalam urutan menurun:

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

Ini akan mengurutkan dalam urutan naik:

usort($array_compare, function($a, $b) {
        return ($b['x1'] - $a['x1']) < 0 ? 1 :-1;
    });
pihu
sumber
1
1) Contoh dan kode tidak konsisten. 2) Ini sudah dijelaskan dengan detail yang luar biasa dalam jawaban di atas. 3) Apakah Anda mungkin mencoba menjawab pertanyaan yang berbeda?
tipuan