วิธีการเรียงลำดับอาร์เรย์หลายมิติตามค่า


1129

ฉันจะจัดเรียงแถวลำดับนี้ตามค่าของคีย์ "คำสั่ง" ได้อย่างไร แม้ว่าค่าจะเรียงตามลำดับ แต่ก็ไม่ได้เป็นเช่นนั้นเสมอไป

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


วิธีที่เร็วที่สุดคือการใช้โมดูลเรียงลำดับ isomorphic ซึ่งทำงานได้ทั้งในเบราว์เซอร์และโหนดสนับสนุนการป้อนข้อมูลทุกประเภทฟิลด์คำนวณและคำสั่งการเรียงลำดับแบบกำหนดเอง
Lloyd

คำตอบ:


1733

ลองใช้usortหากคุณยังใช้ PHP 5.2 หรือเก่ากว่าคุณจะต้องกำหนดฟังก์ชันการเรียงลำดับก่อน:

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

usort($myArray, 'sortByOrder');

เริ่มต้นใน PHP 5.3 คุณสามารถใช้ฟังก์ชั่นที่ไม่ระบุชื่อ:

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

และสุดท้ายด้วย PHP 7 คุณสามารถใช้โอเปอเรเตอร์ยานอวกาศได้ :

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

หากต้องการขยายสิ่งนี้ไปยังการจัดเรียงหลายมิติให้อ้างอิงองค์ประกอบการเรียงลำดับที่สอง / สามถ้าองค์ประกอบแรกเป็นศูนย์ - อธิบายด้านล่างได้ดีที่สุด คุณยังสามารถใช้สิ่งนี้สำหรับการจัดเรียงองค์ประกอบย่อย

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

หากคุณต้องการรักษาความสัมพันธ์ของคีย์ให้ใช้uasort()- ดูการเปรียบเทียบฟังก์ชันการเรียงลำดับอาเรย์ในคู่มือ


2
การใช้ถ้อยคำของฉันปิดไปเล็กน้อยฉันจะแก้ไข สิ่งที่ฉันหมายถึงคือถ้าคุณไม่ได้ใช้ PHP 5.3 คุณต้องสร้างฟังก์ชั่นพิเศษสำหรับการเรียงลำดับนี้โดยเฉพาะ (ซึ่งไม่หรูหราอย่างใด) มิฉะนั้นคุณสามารถใช้ฟังก์ชันที่ไม่ระบุชื่อได้
Christian Studer

23
@ โจนาธาน: คุณไม่เห็นว่างาน PHP ส่วนใหญ่ทำอะไร มันใช้เวลาอาร์เรย์และเริ่มต้นด้วยสององค์ประกอบซึ่งจะส่งผ่านไปยังฟังก์ชั่นที่ผู้ใช้กำหนด ฟังก์ชั่นของคุณมีหน้าที่รับผิดชอบในการเปรียบเทียบพวกเขา: หากองค์ประกอบแรกมากกว่าที่สองให้คืนค่าจำนวนเต็มบวกถ้ามันเล็กลงให้คืนค่าลบ ถ้าพวกเขาเป็น equel ให้ส่งคืน 0 PHP จากนั้นส่งองค์ประกอบอื่น ๆ สองรายการไปยังฟังก์ชันของคุณและดำเนินการต่อไปเรื่อย ๆ จนกว่าอาร์เรย์จะได้รับการจัดเรียง ฟังก์ชันที่นี่สั้นมากมันอาจซับซ้อนกว่านี้ถ้าคุณไม่เปรียบเทียบจำนวนเต็ม
Christian Studer

61
Protip: ใช้uasort()ถ้าคุณต้องการเก็บคีย์อาเรย์ไว้
thaddeusmt

15
ระวังถ้าค่าที่เรียงได้เป็นเลขทศนิยม หากฟังก์ชันการเรียงได้รับ $ a = 1 และ $ b = 0.1 ความแตกต่างคือ 0.9 แต่ฟังก์ชันจะส่งกลับค่า int ในกรณีนี้ 0 ดังนั้น $ a และ $ b จะถือว่าเท่ากันและเรียงลำดับไม่ถูกต้อง มีความน่าเชื่อถือมากกว่าหากเปรียบเทียบว่า $ a มากกว่า $ b หรือเท่ากันแล้วส่งคืน -1, 1 หรือ 0 ตามลำดับ
กรีนแลนด์

37
ฉันใช้เวลาสักครู่เพื่อค้นหา ในการจัดเรียงลำดับย้อนกลับ (DESC) คุณสามารถสลับ $ a และ $ b ดังนั้น $ b ['order'] - $ a ['order']
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");

7
@ noc2spam ฉันดีใจที่ได้ช่วย แต่พิจารณาข้อเสนอแนะของผู้เรียนซึ่งมีประสิทธิภาพมากขึ้นและเป็นระเบียบเรียบร้อยมากขึ้น!
o0 '

1
@ โลริสแน่ใจว่าเพื่อนฉันกำลังตรวจสอบว่าเกินไป เมื่อวานนี้จะได้รับวันรุนแรงในที่ทำงานถ้าฉันไม่พบคำถามนี้ :-)
โกกอล

hmm ไม่สามารถเพิ่มคำตอบ .. ดีฉันวางไว้ที่นี่เพราะฉันไม่ต้องการจุดโง่เหล่านั้น: ดังนั้นสำหรับการจัดเรียงหลายมิติ (เกือบ) ในสิ่งเดียวกัน (srry คุณต้องคัดลอกวางและฟอร์แมตใหม่): ฟังก์ชั่น aasort (& $ array , $ key1, $ key2, $ key3) {$ sorter = array (); $ เกษียณ = array (); รีเซ็ต ($ อาร์เรย์); foreach ($ array เท่ากับ $ ii => $ va) {$ sorter [$ ii] = getPrice ($ va [$ key1] [$ key2] [$ key3]); } arsort ($ sorter); foreach ($ sorter เป็น $ ii => $ va) {$ ret [$ ii] = $ array [$ ii]; } $ array = $ ret; }
Jaxx0rr

3
ง่ายกว่าที่จะใช้มากกว่าคำตอบข้างต้น
Marcel

1
คุณยอดเยี่ยมมาก !! ทำงานได้อย่างมีเสน่ห์เช่นเดียวกับ PHP 7.2 ขอบคุณมาก DEAR :)
Kamlesh

270

ฉันใช้ฟังก์ชั่นนี้:

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

3
ทำงานได้ดีมาก โซลูชันที่ไม่ซ้ำใครสามารถเพิ่มทิศทางการจัดเรียง ขอบคุณ!
Ivo Pereira

2
สำหรับทางเลือกที่รองรับทิศทางการเรียงลำดับและคุณสมบัติเพิ่มเติมมากมายคุณอาจต้องการดูคำตอบของฉันที่นี่ - มันยังมีข้อดีที่ไม่ได้ใช้array_multisortดังนั้นจึงไม่จำเป็นต้องจัดสรรล่วงหน้า$sort_colประหยัดเวลาและหน่วยความจำ .
Jon

ใช้งานได้ดีสำหรับฉัน แต่ ... ทำไมจึงจำเป็นต้องระบุ&$arrแทนเพียง$arr?
Radu Murzea

2
@RaduMurzea ดังนั้นอาร์เรย์จะถูกส่งผ่านโดยการอ้างอิงและสามารถแก้ไขได้โดยฟังก์ชั่นแทนที่จะทำหน้าที่รับสำเนา
Tom Haigh

1
@AdrianP : อาเรย์ถูกส่งผ่านโดยการอ้างอิงดังนั้นมันจะแก้ไขอาเรย์ผ่านแทนที่จะส่งกลับคัดลอกเรียงลำดับ
Tom Haigh

72

ฉันมักจะใช้usortและผ่านฟังก์ชั่นการเปรียบเทียบของตัวเอง ในกรณีนี้มันง่ายมาก:

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

ใน PHP 7 ใช้โอเปอเรเตอร์ยานอวกาศ:

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

4
Dammit ฉันช้าลง 30 วินาที มันไม่ใช่ $ a - $ b ใช่มั้ย
Christian Studer

3
ฉันเข้าใจผิดอยู่เสมอ ให้ฉันคิดจากคู่มือ: ค่าตอบแทนจะต้องน้อยกว่าศูนย์ถ้าอาร์กิวเมนต์แรกถือว่าน้อยกว่าที่สอง ดังนั้นถ้า$a['order']เป็น 3, และ$b['order']6, ฉันจะกลับ -3 แก้ไข?
Jan Fabry

3
ทีนี้, คุณกลับ b - a, มันจะเป็น 3 และเรียงอย่างไม่ถูกต้อง
Christian Studer

26
อา. ตกลง. ฉันใช้เลขคณิตแบบไม่ใช้ตรรกะที่ความคิดในหัวของคุณไม่ตรงกับคำที่คุณสร้าง นี่คือการศึกษาบ่อยที่สุดในบ่ายวันศุกร์
Jan Fabry

ในบางกรณีคำตอบข้างต้นคือส่งคืนผลลัพธ์ที่ผิดพลาด .. อ้างอิงstackoverflow.com/questions/50636981/…
Bilal Ahmed

45

วิธีการหนึ่งในการบรรลุเป้าหมายนี้จะเป็นเช่นนี้

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

ผลลัพธ์:

    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
            )

    )

18

ในการจัดเรียงอาร์เรย์ตามค่าของการใช้คีย์ "title":

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

strcmpเปรียบเทียบสตริง

uasort ()รักษาคีย์อาร์เรย์ตามที่กำหนดไว้


strcmp เป็นตัวช่วยสำคัญสำหรับประเภท varchar ฉันชอบคำตอบนี้สั้นและเร็ว
StudioX

17
$sort = array();
$array_lowercase = array_map('strtolower', $array_to_be_sorted);
array_multisort($array_lowercase, SORT_ASC, SORT_STRING, $alphabetically_ordered_array);

สิ่งนี้จะดูแลทั้งตัวอักษรพิมพ์ใหญ่และพิมพ์เล็ก


4
สิ่งนี้จะตอบคำถามของการเรียงลำดับโดยใช้คีย์อาร์เรย์ที่เฉพาะเจาะจงได้อย่างไร
Seano

12

การใช้งานarray_multisort(),array_map()

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

print_r($array);

การสาธิต


โปรดทราบว่าวิธีการนี้จะส่งการแจ้งเตือน array_multisortการอ้างอิงเป็นพารามิเตอร์แรก
Kami Yang

5

วิธีที่ยืดหยุ่นที่สุดจะใช้วิธีนี้

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

นี่คือเหตุผล:

  • คุณสามารถเรียงลำดับโดยใช้ปุ่มใดก็ได้ (เช่นซ้อนกันเช่น'key1.key2.key3'หรือ['k1', 'k2', 'k3'])

  • ทำงานทั้งในอาเรย์แบบเชื่อมโยงและไม่ใช่แบบเชื่อมโยง ( $assocตั้งค่าสถานะ)

  • ไม่ใช้การอ้างอิง - ส่งคืนอาร์เรย์ที่เรียงลำดับใหม่

ในกรณีของคุณมันจะง่ายเหมือน:

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

วิธีนี้เป็นส่วนหนึ่งของห้องสมุดนี้


1

Let's face it: php ไม่มีฟังก์ชั่นการใช้งานแบบนอกกล่องที่ง่ายต่อการจัดการกับสถานการณ์การเรียงลำดับอาเรย์อย่างถูกต้อง

รูทีนนี้ใช้งานง่ายซึ่งหมายถึงการดีบักและการบำรุงรักษาที่รวดเร็วยิ่งขึ้น:

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

4
"ลองดูสิ: php ไม่มีฟังก์ชั่นนอกกรอบที่ง่ายในการจัดการสถานการณ์การเรียงลำดับของอาร์เรย์ได้อย่างถูกต้อง" นั่นคือสิ่งที่ usort / ksort / asort ได้รับการออกแบบมาสำหรับ ^^ '
Ben Cassinat

3
อันที่จริง PHP มี ฟังก์ชั่นการเรียงลำดับจำนวนมากที่สามารถใช้เพื่อจัดการสถานการณ์จำลองการเรียงลำดับอาเรย์ทุกอันได้
axiac

ในเรื่องเกี่ยวกับการแก้จุดบกพร่องและการบำรุงรักษาด้วยการใช้globalเป็นธงสีแดงขนาดใหญ่และเป็นกำลังใจโดยทั่วไป ทำไมmysql_fetch_arrayถึงแสดงให้เห็นคำถามนี้แทนที่จะเป็นอาร์เรย์แหล่งที่มาของ OP และไม่มีคำอธิบายว่าโค้ดของคุณทำอะไรอยู่และสิ่งใดที่สามารถคาดหวังผลลัพธ์ได้ โดยรวมนี่เป็นวิธีที่ซับซ้อนมากในการบรรลุผลลัพธ์ที่ต้องการ
fyrye

@tonygil ฉันไม่สามารถระบุได้ว่าผลลัพธ์ที่คุณคาดหวังมาจากคำตอบของคุณและชุดข้อมูลของ OP มันอาจจะชัดเจนสำหรับคุณ แต่ฉันไม่รู้ว่าคำตอบของคุณตอบคำถามของ OP อย่างไร อย่างไรก็ตามคุณสามารถส่งต่อแบบอ้างอิงแทนการใช้globalsee: 3v4l.org/FEeFCสิ่งนี้สร้างตัวแปรที่กำหนดไว้อย่างชัดเจนมากกว่าหนึ่งตัวแปรที่สามารถเปลี่ยนแปลงและเข้าถึงได้ทั่วโลก
fyrye

0

คุณสามารถจัดเรียงอาร์เรย์หลายมิติสำหรับค่าหลายค่าเช่น

$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"
    ],

];

กับ

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

เอาต์พุตโดยใช้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) ใช้strcmpจะเป็นตัวเลือกที่ดีในการเปรียบเทียบสตริง

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