Bagaimana Mengurutkan Array Multi-Dimensi berdasarkan Nilai?

1129

Bagaimana saya bisa mengurutkan array ini dengan nilai kunci "pesanan"? Meskipun nilainya saat ini berurutan, nilainya tidak selalu.

Array
(
    [0] => Array
        (
            [hashtag] => a7e87329b5eab8578f4f1098a152d6f4
            [title] => Flower
            [order] => 3
        )

    [1] => Array
        (
            [hashtag] => b24ce0cd392a5b0b8dedc66c25213594
            [title] => Free
            [order] => 2
        )

    [2] => Array
        (
            [hashtag] => e7d31fc0602fb2ede144d18cdffd816b
            [title] => Ready
            [order] => 1
        )
)
Stefan
sumber
cara tercepat adalah menggunakan isomorfik modul array- yang bekerja secara native di kedua browser dan node, mendukung semua jenis input, bidang yang dikomputasi dan pesanan penyortiran khusus.
Lloyd

Jawaban:

1734

Coba usort , Jika Anda masih menggunakan PHP 5.2 atau sebelumnya, Anda harus mendefinisikan fungsi penyortiran terlebih dahulu:

function sortByOrder($a, $b) {
    return $a['order'] - $b['order'];
}

usort($myArray, 'sortByOrder');

Mulai di PHP 5.3, Anda dapat menggunakan fungsi anonim:

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

Dan akhirnya dengan PHP 7 Anda dapat menggunakan operator pesawat ruang angkasa :

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

Untuk memperluas ini ke penyortiran multi-dimensi, referensi elemen penyortiran kedua / ketiga jika yang pertama adalah nol - paling baik dijelaskan di bawah ini. Anda juga dapat menggunakan ini untuk mengurutkan pada sub-elemen.

usort($myArray, function($a, $b) {
    $retval = $a['order'] <=> $b['order'];
    if ($retval == 0) {
        $retval = $a['suborder'] <=> $b['suborder'];
        if ($retval == 0) {
            $retval = $a['details']['subsuborder'] <=> $b['details']['subsuborder'];
        }
    }
    return $retval;
});

Jika Anda perlu mempertahankan asosiasi kunci, gunakan uasort()- lihat perbandingan fungsi penyortiran array dalam manual

Christian Studer
sumber
2
Ungkapan saya sedikit salah, saya akan mengeditnya. Yang saya maksudkan adalah bahwa jika Anda tidak menggunakan PHP 5.3, Anda perlu membuat fungsi khusus hanya untuk penyortiran khusus ini (yang entah bagaimana tidak terlalu elegan). Kalau tidak, Anda bisa menggunakan fungsi anonim di sana.
Christian Studer
23
@ Jonathan: Anda tidak bisa melihat sebagian besar pekerjaan yang dilakukan PHP. Dibutuhkan array dan dimulai dengan dua elemen, yang diteruskan ke fungsi yang ditentukan pengguna ini. Fungsi Anda kemudian bertanggung jawab untuk membandingkannya: Jika elemen pertama lebih besar dari yang kedua, kembalikan bilangan bulat positif, jika lebih kecil, kembalikan yang negatif. Jika mereka equel, kembalikan 0. PHP lalu kirim dua elemen lainnya ke fungsi Anda dan lanjutkan sampai array telah diurutkan. Fungsi di sini sangat singkat, mungkin jauh lebih rumit jika Anda tidak akan membandingkan bilangan bulat.
Christian Studer
61
Protip: gunakan uasort()jika Anda ingin mempertahankan kunci array.
thaddeusmt
15
Hati-hati jika nilai yang dapat diurutkan adalah angka desimal. Jika fungsi pengurutan mendapatkan $ a = 1 dan $ b = 0,1, perbedaannya adalah 0,9, tetapi fungsi mengembalikan int, dalam hal ini 0, jadi $ a dan $ b dianggap sama dan diurutkan secara salah. Lebih dapat diandalkan untuk membandingkan jika $ a lebih besar dari $ b atau sama, dan mengembalikan -1, 1 atau 0 sesuai.
Greenlandi
37
Butuh beberapa saat untuk mengetahuinya. Untuk mengurutkan urutan terbalik (DESC) Anda dapat beralih $ a dan $ b. Jadi $ b ['pesanan'] - $ a ['pesanan']
JanWillem
285
function aasort (&$array, $key) {
    $sorter=array();
    $ret=array();
    reset($array);
    foreach ($array as $ii => $va) {
        $sorter[$ii]=$va[$key];
    }
    asort($sorter);
    foreach ($sorter as $ii => $va) {
        $ret[$ii]=$array[$ii];
    }
    $array=$ret;
}

aasort($your_array,"order");
o0 '.
sumber
7
@ noc2spam Saya senang membantu, tetapi pertimbangkan mengikuti saran yang lebih efisien dan pasti lebih rapi!
o0 '.
1
@ Lohoris yakin Bung aku memeriksa itu juga. Kemarin akan menjadi hari yang lebih sulit di kantor jika saya tidak menemukan pertanyaan ini :-)
Gogol
hmm tidak bisa menambahkan jawaban .. yah saya taruh di sini karena saya tidak perlu poin bodoh itu: jadi untuk multidimensi semacam itu (hampir) hal yang sama (srry Anda harus menyalin paste dan memformatnya kembali): function aasort (& $ array , $ key1, $ key2, $ key3) {$ sorter = array (); $ ret = array (); reset ($ array); foreach ($ array as $ ii => $ va) {$ sorter [$ ii] = getPrice ($ va [$ key1] [$ key2] [$ key3]); } arsort ($ sorter); foreach ($ sorter as $ ii => $ va) {$ ret [$ ii] = $ array [$ ii]; } $ array = $ ret; }
Jaxx0rr
3
Jauh lebih mudah untuk diterapkan daripada jawaban di atas
Marcel
1
KAMU MENAKJUBKAN!! BEKERJA SEPERTI CHARM UNTUK PHP 7.2 TERIMA KASIH SANGAT HATI :)
Kamlesh
270

Saya menggunakan fungsi ini:

function array_sort_by_column(&$arr, $col, $dir = SORT_ASC) {
    $sort_col = array();
    foreach ($arr as $key=> $row) {
        $sort_col[$key] = $row[$col];
    }

    array_multisort($sort_col, $dir, $arr);
}


array_sort_by_column($array, 'order');
Tom Haigh
sumber
3
Bekerja dengan sangat baik. Solusi unik untuk dapat menambahkan arah pengurutan. Terima kasih!
Ivo Pereira
2
Untuk alternatif yang mendukung pengurutan arah dan banyak fitur tambahan, Anda mungkin ingin melihat jawaban saya di sini - ini juga memiliki keuntungan yang tidak digunakan array_multisortdan karenanya tidak perlu melakukan pra-alokasi $sort_col, menghemat waktu dan memori .
Jon
Bekerja bagus untuk saya, tapi ... mengapa perlu untuk menentukan &$arrbukan hanya $arr?
Radu Murzea
2
@ RaduMurzea sehingga array dilewatkan dengan referensi dan dapat dimodifikasi oleh fungsi, daripada fungsi yang menerima salinan
Tom Haigh
1
@AdrianP. : array dilewatkan dengan referensi sehingga akan memodifikasi array yang lewat daripada mengembalikan salinan yang diurutkan
Tom Haigh
72

Saya biasanya menggunakan usort , dan melewati fungsi perbandingan saya sendiri. Dalam hal ini, sangat sederhana:

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

Di PHP 7 menggunakan operator pesawat ruang angkasa:

usort($array, function($a, $b) {
    return $a['order'] <=> $b['order'];
});
Jan Fabry
sumber
4
Sial, aku lebih lambat 30 detik. Bukankah itu $ a - $ b?
Christian Studer
3
Saya selalu salah. Biarkan saya berpikir dari manual: nilai balik harus kurang dari nol jika argumen pertama dianggap kurang dari yang kedua. Jadi jika $a['order']3, dan $b['order']6, saya akan kembali -3. Benar?
Jan Fabry
3
Nah, Anda mengembalikan b - a, jadi 3. Dan dengan demikian diurutkan secara salah.
Christian Studer
26
Ah. BAIK. Saya menggunakan aritmatika non-logis, di mana ide di kepala Anda tidak cocok dengan kata-kata yang Anda hasilkan. Ini dipelajari paling sering pada hari Jumat sore.
Jan Fabry
dalam beberapa kasus jawaban di atas adalah hasil yang salah kembali. referensi stackoverflow.com/questions/50636981/…
Bilal Ahmed
45

Satu pendekatan untuk mencapai ini adalah seperti ini

    $new = [
              [
                'hashtag' => 'a7e87329b5eab8578f4f1098a152d6f4',
                'title' => 'Flower',
                'order' => 3,
              ],

              [
                'hashtag' => 'b24ce0cd392a5b0b8dedc66c25213594',
                'title' => 'Free',
                'order' => 2,
              ],

              [
                'hashtag' => 'e7d31fc0602fb2ede144d18cdffd816b',
                'title' => 'Ready',
                'order' => 1,
              ],
    ];

    $keys = array_column($new, 'order');

    array_multisort($keys, SORT_ASC, $new);

    var_dump($new);

Hasil:

    Array
    (
        [0] => Array
            (
                [hashtag] => e7d31fc0602fb2ede144d18cdffd816b
                [title] => Ready
                [order] => 1
            )

        [1] => Array
            (
                [hashtag] => b24ce0cd392a5b0b8dedc66c25213594
                [title] => Free
                [order] => 2
            )

        [2] => Array
            (
                [hashtag] => a7e87329b5eab8578f4f1098a152d6f4
                [title] => Flower
                [order] => 3
            )

    )
ajuchacko91
sumber
18

Untuk mengurutkan array berdasarkan nilai kunci "judul" gunakan:

uasort($myArray, function($a, $b) {
    return strcmp($a['title'], $b['title']);
});

strcmp membandingkan string.

uasort () mempertahankan kunci array seperti yang ditentukan.

BK
sumber
strcmp adalah bantuan penting untuk tipe varchar, saya menyukai jawaban ini untuk pendek dan cepat
StudioX
17
$sort = array();
$array_lowercase = array_map('strtolower', $array_to_be_sorted);
array_multisort($array_lowercase, SORT_ASC, SORT_STRING, $alphabetically_ordered_array);

Ini menangani kedua huruf besar dan kecil.

Nitrodbz
sumber
4
Bagaimana ini menjawab pertanyaan pengurutan dengan kunci array tertentu?
Seano
12

Gunakan array_multisort(),array_map()

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

print_r($array);

DEMO

Ghanshyam Nakiya
sumber
Perhatikan bahwa pendekatan ini akan mengeluarkan pemberitahuan. array_multisortreferensi itu parameter pertama.
Kami Yang
5

Pendekatan yang paling fleksibel adalah menggunakan metode ini

Arr::sortByKeys(array $array, $keys, bool $assoc = true): array

inilah sebabnya:

  • Anda dapat mengurutkan berdasarkan tombol apa saja (juga suka 'key1.key2.key3'atau ['k1', 'k2', 'k3'])

  • Bekerja baik pada array asosiatif dan tidak asosiatif ( $assocbendera)

  • Itu tidak menggunakan referensi - mengembalikan array yang diurutkan baru

Dalam kasus Anda, sesederhana:

$sortedArray = Arr::sortByKeys($array, 'order');

Metode ini adalah bagian dari perpustakaan ini .

Pekerjaan kecil
sumber
1

Mari kita hadapi itu: php TIDAK memiliki fungsi sederhana di luar kotak untuk menangani dengan benar setiap skenario susunan array.

Rutin ini intuitif, yang berarti lebih cepat debugging dan pemeliharaan:

// automatic population of array
$tempArray = array();
$annotations = array();
// ... some code
// SQL $sql retrieves result array $result 
// $row[0] is the ID, but is populated out of order (comes from 
// multiple selects populating various dimensions for the same DATE 
// for example
while($row = mysql_fetch_array($result)) {
    $needle = $row[0];
    arrayIndexes($needle);  // create a parallel array with IDs only
    $annotations[$needle]['someDimension'] = $row[1]; // whatever
}
asort($tempArray);
foreach ($tempArray as $arrayKey) {
    $dataInOrder = $annotations[$arrayKey]['someDimension']; 
    // .... more code
}

function arrayIndexes ($needle) {
    global $tempArray;
    if (!in_array($needle,$tempArray)) {
        array_push($tempArray,$needle);
    }
}
tony gil
sumber
4
"Mari kita hadapi: php TIDAK memiliki fungsi sederhana di luar kotak untuk menangani dengan benar setiap skenario jenis array." Itulah yang dirancang untuk usort / ksort / asort ^ ^ '
Ben Cassinat
3
Sebenarnya PHP memiliki banyak fungsi penyortiran yang dapat digunakan untuk menangani setiap skenario susunan array.
aksioma
Berkenaan dengan debugging dan pemeliharaan, penggunaan globalbendera merah besar dan umumnya tidak disarankan . Mengapa mysql_fetch_arraydiperlihatkan untuk pertanyaan ini alih-alih susunan sumber OP, dan bahwa tidak ada penjelasan tentang apa yang kode Anda lakukan dan apa yang bisa diharapkan hasilnya? Secara keseluruhan ini adalah pendekatan yang sangat kompleks untuk mencapai hasil akhir yang diinginkan.
fyrye
@tonygil Saya tidak dapat menentukan hasil apa yang Anda harapkan dari jawaban Anda dan dataset OP. Ini mungkin jelas bagi Anda, tetapi saya tidak tahu bagaimana jawaban Anda menjawab pertanyaan OP. Namun, Anda dapat melewati referensi daripada menggunakan globallihat: 3v4l.org/FEeFC Ini menghasilkan variabel yang didefinisikan secara eksplisit, bukan yang dapat diubah dan diakses secara global.
fyrye
0

Anda juga bisa mengurutkan array multi dimensi untuk beberapa nilai seperti

$arr = [
    [
        "name"=> "Sally",
        "nick_name"=> "sal",
        "availability"=> "0",
        "is_fav"=> "0"
    ],
    [
        "name"=> "David",
        "nick_name"=> "dav07",
        "availability"=> "0",
        "is_fav"=> "1"
    ],
    [
        "name"=> "Zen",
        "nick_name"=> "zen",
        "availability"=> "1",
        "is_fav"=> "0"
    ],
    [
        "name"=> "Jackson",
        "nick_name"=> "jack",
        "availability"=> "1",
        "is_fav"=> "1"
    ],
    [
        "name"=> "Rohit",
        "nick_name"=> "rod",
        "availability"=> "0",
        "is_fav"=> "0"
    ],

];

dengan

usort($arr,function($a,$b){
    $c = $b['is_fav'] - $a['is_fav'];
    $c .= $b['availability'] - $a['availability'];
    $c .= strcmp($a['nick_name'],$b['nick_name']);
    return $c;
});

Output menggunakan print_r($arr):

Array
(
    [0] => Array
        (
            [name] => Jackson
            [nick_name] => jack
            [availability] => 1
            [is_fav] => 1
        )

    [1] => Array
        (
            [name] => David
            [nick_name] => dav07
            [availability] => 0
            [is_fav] => 1
        )

    [2] => Array
        (
            [name] => Zen
            [nick_name] => zen
            [availability] => 1
            [is_fav] => 0
        )

    [3] => Array
        (
            [name] => Rohit
            [nick_name] => rod
            [availability] => 0
            [is_fav] => 0
        )

    [4] => Array
        (
            [name] => Sally
            [nick_name] => sal
            [availability] => 0
            [is_fav] => 0
        )

)

PS) menggunakan strcmp akan menjadi pilihan yang baik untuk membandingkan string.

StudioX
sumber