【PHP、JavaScript】陣列自定義排序

【PHP、JavaScript】陣列自定義排序

本篇重點

  • PHP 的 usort() 陣列自定義排序
  • JavaScript 的 .sort() 陣列自定義排序
  • 自定義排序比較函數的規則
  • PHP usort() 和 JavaScript .sort() 的反向排序
  • 陣列自定義排序應用範例

PHP 的 usort()

根據自定義的邏輯對陣列進行排序,不保留鍵名,僅針對值進行排序,並且直接修改原陣列

usort($array, $callback);

php
1
2
3
usort($array, function($a, $b) {
return $a <=> $b;
});
  • $array 為欲排序的陣列
  • $callback 為比較函數

比較函數的規則

  • return < 0$a 排在 $b
  • return > 0$a 排在 $b
  • return === 0$a$b 順序保持不變

<=> 介紹

<=> 是 PHP 7 引入的「太空船運算子」(Spaceship Operator),用來比較兩個值的大小,返回三種結果

  • 返回 -1:左邊的值小於右邊的值
  • 返回 0:左邊的值等於右邊的值
  • 返回 1:左邊的值大於右邊的值

範例

  • 情境一,對一組隨機亂數的陣列,依小到大做排序 (升序)
php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$array = [5, 2, 9, 1, 3];

// 方法一
usort($array, function($a, $b) {
return $a - $b; // 差值決定排序順序
});

// 方法二
usort($array, function($a, $b) {
return $a <=> $b;
});

// 方法三 (單層的陣列可以直接使用 sort() 排序,預設排序是小到大)
sort($array);

print_r($array);
// 輸出: [1, 2, 3, 5, 9]
  • 情境二,假設得到一組陣列資料,裡面有各個活動的資訊,依需求對陣列排序。

整體順序是 1.未到期活動 2.已到期活動,且皆以最新到最舊活動排序,執行方式為判斷活動結束時間 end_date 是否小於現在時間 (是否到期),未到期活動排在已到期活動前面,再以活動開始時間 start_date 大到小排序

php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// 活動資訊陣列
$array = [
[
"id" => 1,
"event_time" => [
"start_date" => 1730084400, // 2024-10-28 11:00:00
"end_date" => 1731513659 // 2024-11-14 00:00:59
]
],
[
"id" => 2,
"event_time" => [
"start_date" => 1729512000, // 2024-10-21 20:00:00
"end_date" => 1731254400 // 2024-11-11 00:00:00
]
],
[
"id" => 3,
"event_time" => [
"start_date" => 1730102400, // 2024-10-28 16:00:00
"end_date" => 1731686400 // 2024-11-16 00:00:00
]
]
];

// 排序函數
usort($array, function ($a, $b) {
$current_time = time();
$a_end_date = $a['event_time']['end_date'];
$b_end_date = $b['event_time']['end_date'];
$a_start_date = $a['event_time']['start_date'];
$b_start_date = $b['event_time']['start_date'];

// 首先判斷是否過期
$a_is_expired = $a_end_date < $current_time;
$b_is_expired = $b_end_date < $current_time;

// 如果一個過期一個未過期,將未過期的排前面
if ($a_is_expired !== $b_is_expired) {
return $a_is_expired <=> $b_is_expired;
}

// 否則依據 start_date 從大到小排序
return $b_start_date <=> $a_start_date;
});

print_r($array);

JavaScript 的 .sort()

.sort() 是 JavaScript 提供的陣列排序方法,與 PHP 的 usort() 規則非常相似,允許傳入自定義的比較函數,並且直接修改原陣列。

array.sort([compareFunction])

js
1
2
3
array.sort(function (a, b) {
return a - b;
});
  • array 為欲排序的陣列
  • compareFunction 為比較函數

比較函數的規則:

  • return < 0a 排在 b
  • return > 0a 排在 b
  • return === 0:順序保持不變

健忘筆記

JavaScript 沒有 <=> 運算子

範例

  • 情境一,對一組隨機亂數的陣列,依小到大做排序 (升序)
js
1
2
3
4
5
6
7
8
9
10
11
12
let array = [5, 2, 9, 1, 3];

// 方法一,.sort() 預設就是以小排到大
array.sort();

// 方法二,差值決定排序順序
array.sort(function (a, b) {
return a - b;
});

console.log(array);
// 輸出: [1, 2, 3, 5, 9]
  • 情境二,假設需要依照指定順序照片排序

陣列內是指定順序的照片編號

html
1
2
3
4
5
<div class="images_container">
<img data-id="1" src="https://forgetfulengineer.github.io/gallery/covers/Tracking-File-Modification-History.png"></img>
<img data-id="2" src="https://forgetfulengineer.github.io/gallery/covers/Understanding-five-Common-Relative-Units.png"></img>
<img data-id="3" src="https://forgetfulengineer.github.io/gallery/covers/Using-less-to-View-Files.png"></img>
</div>
js
1
2
3
4
5
6
7
8
9
10
11
let images_sorting_arr = [3, 1, 2];
let images_container = $(".images_container");
let images = $(".images_container [data-id]").toArray();

category_news.sort(function (a, b) {
return (
images_sorting_arr.indexOf($(a).data("id")) - images_sorting_arr.indexOf($(b).data("id"))
);
});
images_container.empty();
$(images).appendTo(images_container);

PHP usort() 的反向排序

php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$array = [5, 2, 9, 1, 3];

// 方法一
usort($array, function($a, $b) {
return $b - $a;
});

// 方法二
usort($array, function($a, $b) {
return $b <=> $a;
});

// 方法三 (使用負號來反轉比較結果)
usort($array, function($a, $b) {
return -($a <=> $b);
});

// 方法四 (單層的陣列可以直接使用 rsort() 排序)
rsort($array);

print_r($array);
// 輸出: [9, 5, 3, 2, 1]

JavaScript .sort() 的反向排序

js
1
2
3
4
5
6
7
8
9
10
11
12
13
let array = [5, 2, 9, 1, 3];

// 方法一,先用 .sort() 小排到大,再用 .reverse() 把陣列順序反轉
array.sort();
array.reverse();

// 方法二,差值決定排序順序
array.sort(function (a, b) {
return b - a;
});

console.log(array);
// 輸出: [9, 5, 3, 2, 1]

結論

PHP 的 usort() 和 JavaScript 的 .sort() 是功能非常相似的自定義排序工具,並遵循相同的比較函數邏輯判斷

  • return < 0$a 排在 $b
  • return > 0$a 排在 $b
  • return === 0$a$b 順序保持不變

自定義排序可以更靈活的依照需求得到想要的陣列,在開發上很有幫助!

延伸閱讀

作者

健忘工程師

發表於

2024-12-11

更新於

2024-12-11

許可協議


評論

複製完成