PHP Sortir Array Berdasarkan Nilai SubArray


110

Saya memiliki struktur array berikut:

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

Apa cara terbaik untuk mengurutkan larik secara bertahap, berdasarkan optionNumber ?

Jadi hasilnya terlihat seperti:

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

Jawaban:


204

Gunakan usort.

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

...

usort($array, "cmp_by_optionNumber");

Di PHP ≥5.3, Anda harus menggunakan fungsi anonim sebagai gantinya:

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

Perhatikan bahwa kedua kode di atas menganggap $a['optionNumber']adalah bilangan bulat. Gunakan @St. Solusi John Johnson jika itu adalah string.


Di PHP ≥7.0, gunakan operator pesawat ruang angkasa<=> alih-alih pengurangan untuk mencegah masalah luapan / pemotongan.

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

1
Itu tidak benar-benar membantu saya karena usort mengharuskan Saya menyediakannya fungsi untuk digunakan - yang merupakan bagian sulit yang tidak bisa saya
pikirkan

17
Yah, dia baru saja memberi Anda fungsi untuk digunakan. Dan Anda harus menerima bahwa tidak selalu ada fungsi bawaan untuk melakukan apa yang Anda inginkan, Anda harus menulisnya sendiri. Fungsi perbandingan hanya memerlukan pengembalian 1, 0, atau -1 yang menunjukkan urutan untuk dua elemen.
Tesserex

1
Saya melihat lebih jauh ke dalam usort dan itu sebenarnya cukup keren. Saya menulis fungsi perbandingan sederhana dengan yang di atas, namun melewatkan '=='. Terima kasih atas bantuannya
Sjwdavies

3
Sekarang juga sebagai penutup: - usort ($ array, function ($ a, $ b) {return $ b ["optionNumber"] - $ a ["optionNumber"];});
Joeri

1
@ KiloumapL'artélon Jika hasilnya adalah < 0, ini memberitahu fungsi sortir yang aharus muncul sebelumnya b. Jika sudah > 0maka bharus muncul sebelumnya a.
kennytm

57

Menggunakan usort

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

7
@BenSinclair, itu karena solusi Kenny adalah untuk angka, solusi ini untuk string. Keduanya benar :-) +1 untuk alternatif ini.
kubilay

Untuk pengurutan yang tidak peka huruf besar / kecil, gunakan strcasecmp daripada strcmp
user570605

Bisakah kita mendefinisikan kunci untuk urutan kedua dalam array berarti kita melakukan pengurutan pertama dengan optionNumber kemudian mengurutkan dengan lastUpdated. Bagaimana bisa melakukan hal ini?
Bhavin Thummar

16

Saya menggunakan kedua solusi oleh KennyTM dan AJ Quick dan muncul dengan fungsi yang dapat membantu dalam masalah ini untuk banyak kasus seperti menggunakan penyortiran ASC atau DESC atau mempertahankan kunci atau jika Anda memiliki objek sebagai turunan dari array .

Berikut adalah fungsi ini (berfungsi untuk PHP7 dan lebih tinggi karena operator pesawat luar angkasa):

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

Pemakaian:

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

Edit

Bagian pertama dapat ditulis ulang menggunakan uasort()dan fungsinya akan lebih pendek (berfungsi untuk PHP7 dan lebih tinggi karena operator pesawat luar angkasa):

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

Ini adalah jawaban terbaik yang paling berguna di sini, harus di atas;)
Edi Budimilic

@EdiBudimilic terima kasih, saya menghargainya! Ngomong-ngomong, saya telah memperbarui jawaban saya dan menambahkan versi yang lebih pendek dari fungsi ini :)
Pigalev Pavel

1
Untuk membuat ini bekerja untuk saya, saya harus menggunakan >(lebih besar dari) daripada -(minus) saat membandingkan $adan $bnilai karena saya membandingkan string. Masih berfungsi.
Yakobus

1
@James kamu benar. Saya mengubah jawabannya dan menambahkan penggunaan operator pesawat luar angkasa (<=>). Sekarang seharusnya bekerja dengan baik.
Pigalev Pavel

Adakah cara untuk membuat kasus ini tidak peka?
loeffel

4

Tombol-tombol tersebut dilepas saat menggunakan fungsi seperti di atas. Jika kunci penting, fungsi berikut akan mempertahankannya ... tetapi foreach loop cukup tidak efisien.

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

Gunakan arsort daripada asort jika Anda ingin dari tinggi ke rendah.

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


4

Menggunakan array_multisort (), array_map ()

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

print_r($array);

DEMO


2
Ini hanya bekerja dengan sangat mudah. Terima kasih. Yang harus saya lakukan adalah mengubah nama kolom saya dan itu berhasil.
Kobus Myburgh

2
Ini juga mempertahankan kunci untuk array induk
JonnyS

3

PHP 5.3+

usort($array, function($a,$b){ return $a['optionNumber']-$b['optionNumber'];} );
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.