iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 5
1
自我挑戰組

花式PHP系列 第 5

Array:排序

/images/emoticon/emoticon39.gif
今天的內容比較偷懶一點,

畢竟這些排序函式的執行都只是一行內的事情,
而這些函式的共通點都是在哪裡用它比如何使用它還重要...。

儘管如此,知道有這些函式的存在還是很重要的,
希望大家看完這一系列的陣列函式介紹文可以使出各種自創的組合技!

比如什麼 ↑ ↑ ↓ ↓ ← → ← → B A的啦

array_reverse()

這個函式可以產生一個順序完全相反的陣列。

基本用法

<?php

$data = [
    1,
    2,
    3,
    4,
    5
];

print_r(array_reverse($data));

// output:
// Array
// (
//     [0] => 5
//     [1] => 4
//     [2] => 3
//     [3] => 2
//     [4] => 1
// )

恩,真的是毫無懸念的產出一個 [5, 4, 3, 2, 1] 了呢!

第二個參數決定是否要保留 key

我們都知道,宣告陣列不指定 key 的時候 PHP 會自己給他們純數字的 key。

問題來了,上面的程式碼即使加上第二個參數,結果也毫無懸念的好猜,
但如果 我們在宣告陣列時手動幫它亂指定 key 呢?排序結果會一樣嗎?

在測試之前先講結論:不會。

假設

為了執行這個測試,我們會宣告一個 values 一樣是 [1, 2, 3, 4, 5] 的陣列,
但 key 就是亂給的。

  1. 假設 array_reverse() 不受 key 影響,那排序後的 key 應該也正好是以相反的順序呈現的。
  2. 假設 array_reverse() 受 key 影響,那...會發生什麼事呢?

測試假設1

<?php

$data = [
    3 => 1,
    1 => 2,
    2 => 3,
    4 => 4,
    0 => 5
];

print_r(array_reverse($data, TRUE));

// output:
// Array
// (
//     [0] => 5
//     [4] => 4
//     [2] => 3
//     [1] => 2
//     [3] => 1
// )

恩,
看起來 values 真的完全不受自訂 keys 的影響!

那沒事了各位,
我們繼續看下一個函式吧 :3

shuffle()

注意了各位,這個函式可以讓陣列的 values 排成你爸媽都認不得的樣子!
而且它是直接對傳進去的 array 做操作!

PHP 這些 array functions 的慣例是:

  1. 直接存取傳入陣列的,通常回傳的是 boolean
  2. 根據傳入陣列產生新陣列的,回傳的是 array
  3. 用於 flow control、判斷 key 或 value 存在與否的不在此列
<?php

$data = range(1, 20, 3);

// Array
// (
//     [0] => 1
//     [1] => 4
//     [2] => 7
//     [3] => 10
//     [4] => 13
//     [5] => 16
//     [6] => 19
// )

shuffle($data);
print_r($data);

// Array
// (
//     [0] => 4
//     [1] => 13
//     [2] => 19
//     [3] => 7
//     [4] => 16
//     [5] => 1
//     [6] => 10
// )

sort()與它的快樂好夥伴

排序用的函式!我想知道它的人應該時常會遇到它派得上用場的時機吧?
底下用列點的方式介紹這些 functions:

k = key - 對 keys 排序
r = reverse - 反向排序
u = user-defined - 自訂排序邏輯
a = associative array - 排序的同時保留每個 value 原本的 key

function 意義
sort 對 values 排序
asort 對 values 排序且保留其原本的 key
natsort 使用自然排序法來排序 values
ksort 對 keys 排序
rsort 逆向的 sort()
arsort 逆向的 asort()
krsort 逆向的 ksort()

除了上述這些 functions 之外,
其實還有下面三個可以自己寫排序邏輯的 sort function

  1. usort
  2. uasort
  3. uksort

舉個例子:
時值地球曆2200年,地球上所有國家已經結合在一起,
人類也在研發出超光速引擎之後開始進軍其他星系...

但很可惜的,有些種族就是首抽沒抽好,開局就抽了一個帶賽的位置。
我們的地球聯合國附近剛好就有超先進的博格人...QQ

博格女皇決定使用它們手中掌握的殺手鐧 - 一段記載著太陽系各星系資訊的JSON,
並用 PHP 進行 usort 後決定佔領太陽系各星球的順序...

<?php

$json = <<<SOL
[
  {
    "名稱": "水星",
    "類別": "類地行星",
    "人口": 0,
    "衛星數量": 0,
    "備註": ""
  },
  {
    "名稱": "金星",
    "類別": "類地行星",
    "人口": 0,
    "衛星數量": 0,
    "備註": "最亮的行星"
  },
  {
    "名稱": "地球",
    "類別": "類地行星",
    "人口": 6600000000,
    "衛星數量": 1,
    "備註": "最大的類地行星"
  },
  {
    "名稱": "火星",
    "類別": "類地行星",
    "人口": 131465,
    "衛星數量": 2,
    "備註": ""
  },
  {
    "名稱": "木星",
    "類別": "類木行星",
    "人口": 0,
    "衛星數量": 67,
    "備註": "最大的行星"
  },
  {
    "名稱": "土星",
    "類別": "類木行星",
    "人口": 0,
    "衛星數量": 62,
    "備註": "有最寬的行星環"
  },
  {
    "名稱": "天王星",
    "類別": "類木行星",
    "人口": 0,
    "衛星數量": 27,
    "備註": ""
  },
  {
    "名稱": "海王星",
    "類別": "類木行星",
    "人口": 0,
    "衛星數量": 14,
    "備註": ""
  }
]
SOL;

$data = json_decode($json, TRUE);

usort($data, function ($a, $b) {
    /**
     * return >  0    $a 比 $b 還大
     * return == 0    $a 等於 b
     * return <  0    $a 比 $b 還小
     */
    return $a['衛星數量'] - $b['衛星數量'];
});

/*
 * @see http://php.net/manual/en/function.array-column.php
 */
print_r(array_column($data, '名稱'));

// output: (按照衛星數量由小排到大)
// Array
// (
//     [0] => 水星
//     [1] => 金星
//     [2] => 地球
//     [3] => 火星
//     [4] => 海王星
//     [5] => 天王星
//     [6] => 土星
//     [7] => 木星
// )

上一篇
Array:流程控制、迭代操作
下一篇
Array:操作、查詢
系列文
花式PHP31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言