處理多維數組去重時,array_unique() 僅支持一維數組,且基於字符串比較。針對多維關聯數組(如 API 返回的記錄集),需自定義比較邏輯。
$json = '{
"rec_items": [
{"gid": 6326585, "novel_name": "莽荒紀", "author": "我吃西紅柿"},
{"gid": 6109786, "novel_name": "絕世唐門", "author": "唐家三少"}
],
"cate_book_items": [
{"gid": 6326585, "novel_name": "莽荒紀", "author": "我吃西紅柿"}, // 重複
{"gid": 10645516, "novel_name": "完美世界", "author": "辰東"}
]
}';
$data = json_decode($json, true);
$merged = array_merge_recursive($data['rec_items'], $data['cate_book_items']);
// $merged 包含 4 個元素,其中 1 個重複
function multiArrayUnique(array $array): array {
$result = [];
$seen = []; // 存儲已見鍵值簽名
foreach ($array as $key => $value) {
// 生成唯一簽名:排序鍵 + 序列化值(確保順序無關)
ksort($value);
$signature = serialize($value);
if (!isset($seen[$signature])) {
$seen[$signature] = true;
$result[$key] = $value; // 保留原鍵或重新索引
}
}
return $result;
}
// 使用
$unique = multiArrayUnique($merged);
// 結果:3 個元素,重複的 gid=6326585 被移除
function multiArrayUniqueByField(array $array, string $field): array {
$result = [];
$seen = [];
foreach ($array as $item) {
if (!isset($item[$field])) continue; // 跳過無該字段項
$key = $item[$field];
if (!isset($seen[$key])) {
$seen[$key] = true;
$result[] = $item;
}
}
return $result;
}
// 使用:按 gid 去重
$unique = multiArrayUniqueByField($merged, 'gid');
| 方法 | 時間複雜度 | 適用場景 | 備註 |
|---|---|---|---|
in_array() 遍歷檢查 | O(n²) | 小數據集 (<1000) | 簡單但慢 |
serialize() + isset() | O(n) | 完整結構去重、鍵順序不敏感 | 推薦通用方案 |
指定字段 isset($seen[$key]) | O(n) | 業務主鍵去重(如 ID、SKU) | 最快、語義最清晰 |
array_unique() (SORT_REGULAR) | O(n log n) | 一維數組、標量值 | PHP 7.2+ 支持多維但不可靠 |
array_chunk($data, 10000) 分批去重再合併SELECT DISTINCT ON (gid) ... (PostgreSQL) 或 GROUP BY gidmd5(serialize($item)) 作為鍵,比 serialize() 更快['GID'=>1] vs ['gid'=>1] 視為不同,預處理 array_change_key_case()123 vs '123' 序列化不同,預處理類型統一0.1+0.2 序列化不穩定,金額字段建議存整數分__serialize() 或轉數組選擇合適策略:業務主鍵去重用字段法,結構去重用序列化簽名法,大數據推流式/資料庫層面解決。