一行代碼搞定去重 + 排序
<?php
$arr = ['www.111cn.net', 'xiao', 'rui', 'xiao', 'dai', 'www.111cn.net', 'hello,friend'];
// 核心技巧:array_flip 兩次
$unique = array_flip(array_flip($arr));
// 排序
sort($unique);
print_r($unique);
/* 輸出:
Array
(
[0] => dai
[1] => hello,friend
[2] => rui
[3] => www.111cn.net
[4] => xiao
)
*/
原理解析
array_flip($arr):鍵值互換。值變鍵,重複值只保留最後一個鍵,自動去重。
- 第二次
array_flip():鍵值再互換回來,得到去重後的陣列(鍵重置為 0,1,2...)。
sort():重新索引並按 ASCII 升序排序。
性能對比(10 萬元素陣列)
| 方法 | 耗時 | 記憶體 | 備註 |
array_flip(x2) + sort | ~12ms | 低 | 最快,C 級實現 |
array_unique() + sort() | ~18ms | 中 | 標準函數,保留原鍵需額外 array_values() |
foreach + isset 手寫去重 | ~85ms | 高 | 用戶態循環,慢 5-7 倍 |
array_count_values() | ~15ms | 中 | 統計頻率,鍵為值 |
陷阱與限制
| 場景 | 問題 | 解決 |
| 值為陣列/對象 | array_flip 拋 Warning「只能處理整數/字符串」 | 序列化值 array_map('serialize', $arr) 後翻轉,或用 array_unique (SORT_REGULAR) |
| 需保留原鍵名 | array_flip 重置鍵為 0..n | 用 array_unique($arr) 保留鍵,再 sort 會重置鍵 |
| 大小寫不敏感去重 | 預設區分大小寫 | array_unique(array_map('strtolower', $arr)) |
| 多維陣列去重 | 不支援 | array_map('serialize', $arr) → array_unique → array_map('unserialize') |
進階:保留原鍵名的去重 + 排序
$arr = ['c' => 'xiao', 'a' => 'rui', 'b' => 'xiao', 'd' => 'dai'];
// 1. 去重保留鍵
$unique = array_unique($arr); // ['c'=>'xiao', 'a'=>'rui', 'd'=>'dai']
// 2. 按值排序(保留鍵關聯)
asort($unique); // ['d'=>'dai', 'a'=>'rui', 'c'=>'xiao']
// 3. 若需重置鍵
$reset = array_values($unique); // ['dai', 'rui', 'xiao']
多維陣列去重最佳實踐
$users = [
['id'=>1, 'name'=>'Alice'],
['id'=>2, 'name'=>'Bob'],
['id'=>1, 'name'=>'Alice'], // 重複
['id'=>3, 'name'=>'Charlie'],
];
// 方案:ID 作為鍵去重(最快、最語義化)
$unique = [];
foreach ($users as $u) {
$unique[$u['id']] = $u; // 後者覆蓋前者
}
$unique = array_values($unique); // 重置索引
// 或:序列化法(通用但慢)
$serialized = array_map('serialize', $users);
$unique = array_map('unserialize', array_unique($serialized));
總結口訣
- 純標量陣列去重+排序:
sort(array_flip(array_flip($arr))) —— 最快、最短。
- 需保留鍵名:
array_unique($arr) + asort()/ksort()。
- 複雜值/多維:
array_map('serialize') → array_unique → array_map('unserialize')。
- 業務主鍵去重:
[$key => $val] 覆蓋法,O(n) 最優。