PHP เรียงลำดับ Array ตามค่า SubArray


110

ฉันมีโครงสร้างอาร์เรย์ต่อไปนี้:

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

วิธีใดเป็นวิธีที่ดีที่สุดในการสั่งซื้ออาร์เรย์ด้วยวิธีที่เพิ่มขึ้นตามoptionNumber?

ผลลัพธ์จะเป็นดังนี้:

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

คำตอบ:


204

ใช้usort.

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

...

usort($array, "cmp_by_optionNumber");

ใน PHP ≥5.3คุณควรใช้ฟังก์ชันนิรนามแทน:

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

โปรดทราบว่ารหัสทั้งสองข้างบนถือว่า$a['optionNumber']เป็นจำนวนเต็ม ใช้@St. วิธีแก้ปัญหาของ John Johnsonหากเป็นสตริง


ใน PHP ≥7.0ให้ใช้ตัวดำเนินการยานอวกาศ<=>แทนการลบเพื่อป้องกันปัญหาล้น / การตัดทอน

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

1
นั่นไม่ได้ช่วยฉันอย่างแท้จริงเพราะ usort ต้องการฉันจัดให้มีฟังก์ชั่นการใช้งาน - ซึ่งเป็นบิตที่ยากที่ฉันไม่สามารถหัวของฉันได้
Sjwdavies

17
เขาแค่ให้ฟังก์ชันการใช้งานแก่คุณ และคุณจะต้องยอมรับว่าไม่มีฟังก์ชันในตัวที่จะทำสิ่งที่คุณต้องการได้เสมอไปคุณต้องเขียนด้วยตัวเอง ฟังก์ชันการเปรียบเทียบเพียงแค่ต้องการผลตอบแทน 1, 0 หรือ -1 เพื่อระบุลำดับการจัดเรียงสำหรับสององค์ประกอบ
Tesserex

1
ฉันมองไปไกลกว่านั้นในการหาทางเลือกและมันก็ค่อนข้างเจ๋ง ฉันเขียนฟังก์ชันเปรียบเทียบอย่างง่ายกับฟังก์ชันข้างต้น แต่พลาด '==' ขอบคุณสำหรับความช่วยเหลือ
Sjwdavies

3
ตอนนี้ยังเป็นการปิด: - usort ($ array, function ($ a, $ b) {return $ b ["optionNumber"] - $ a ["optionNumber"];});
Joeri

1
@ KiloumapL'artélonถ้าผลที่ได้คือ< 0จะบอกฟังก์ชั่นการจัดเรียงที่ควรปรากฏก่อนa bถ้าเป็น> 0แล้วควรจะปรากฏก่อนb a
kennytm

57

ใช้ usort

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

7
@BenSinclair นั่นเป็นเพราะโซลูชันของ Kenny สำหรับตัวเลขวิธีนี้ใช้สำหรับสตริง ถูกต้องทั้งคู่ :-) +1 สำหรับทางเลือกนี้
kubilay

สำหรับการเรียงลำดับที่ไม่คำนึงถึงตัวพิมพ์เล็กและใหญ่ให้ใช้ strcasecmp แทน strcmp
user570605

เราสามารถกำหนดคีย์สำหรับลำดับที่สองในอาร์เรย์ได้หรือไม่หมายความว่าเราทำการเรียงลำดับครั้งแรกด้วย optionNumber จากนั้นเรียงลำดับด้วย lastUpdated ทำสิ่งนี้ได้อย่างไร?
ภวินทุมมาร์

16

ผมใช้การแก้ปัญหาทั้งสองโดยKennyTMและAJ ด่วนและมาพร้อมกับฟังก์ชั่นที่สามารถช่วยในเรื่องนี้ได้หลายกรณีเช่นการใช้ ASC DESC หรือเรียงลำดับหรือรักษากุญแจหรือหากคุณมีวัตถุที่เป็นเด็กของอาร์เรย์

นี่คือฟังก์ชั่นนี้ (ใช้ได้กับ PHP7 และสูงกว่าเนื่องจากตัวดำเนินการยานอวกาศ):

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

การใช้งาน:

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

แก้ไข

ส่วนแรกสามารถเขียนใหม่ได้โดยใช้uasort()ฟังก์ชันจะสั้นลง (ใช้ได้กับ PHP7 และสูงกว่าเนื่องจากตัวดำเนินการยานอวกาศ):

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

นี่คือคำตอบที่มีประโยชน์ที่สุดที่นี่ควรอยู่ด้านบน;)
Edi Budimilic

@EdiBudimilic ขอบคุณฉันซาบซึ้ง! ฉันได้อัปเดตคำตอบและเพิ่มเวอร์ชันที่สั้นกว่าของฟังก์ชันนี้แล้ว :)
Pigalev Pavel

1
เพื่อให้สิ่งนี้ได้ผลสำหรับฉันฉันต้องใช้>(มากกว่า) แทน-(ลบ) เมื่อเปรียบเทียบ$aและ$bค่าเนื่องจากฉันกำลังเปรียบเทียบสตริง ยังคงใช้งานได้
James

1
@ เจมส์คุณพูดถูก ฉันเปลี่ยนคำตอบและเพิ่มการใช้ตัวดำเนินการยานอวกาศ (<=>) ตอนนี้ควรใช้งานได้ดี
Pigalev Pavel

มีวิธีที่จะทำให้กรณีนี้ไม่มีความสำคัญหรือไม่?
loeffel

4

ปุ่มจะถูกลบออกเมื่อใช้ฟังก์ชันเช่นเดียวกับด้านบน หากคีย์มีความสำคัญฟังก์ชันต่อไปนี้จะคงไว้ ... แต่ foreach loops นั้นค่อนข้างไม่มีประสิทธิภาพ

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

ใช้ arsort แทน asort ถ้าคุณต้องการจากสูงไปต่ำ

เครดิตรหัส: http://www.firsttube.com/read/sorting-a-multi-dimensional-array-with-php/


4

ใช้ array_multisort (), array_map ()

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

print_r($array);

การสาธิต


2
แค่นี้ก็ใช้งานได้ง่ายมาก ขอบคุณ. สิ่งที่ฉันต้องทำคือเปลี่ยนชื่อคอลัมน์ของฉันและมันได้ผล
Kobus Myburgh

2
นอกจากนี้ยังเก็บรักษาคีย์สำหรับอาร์เรย์หลัก
JonnyS

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.