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
                )
    )
Sjwdavies.dll
sumber

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'];
});
kennytm
sumber
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']);
 }
St. John Johnson
sumber
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;
}
Pigalev Pavel
sumber
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/

AJ Cepat
sumber
4

Menggunakan array_multisort (), array_map ()

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

print_r($array);

DEMO

Ghanshyam Nakiya
sumber
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'];} );
Samer Ata
sumber