將多維陣列中某欄位(如 category_id、user_id)值相同的元素聚合為子陣列,常用於:
<?php
/**
* 依指定鍵值將多維陣列分組合併
*
* @param array $array 來源陣列
* @param mixed $start 當前分組的基準鍵值(首次呼叫傳入 $array[0][$key])
* @param string $key 分組依據的鍵名
* @param string $newkey 合併後子陣列的鍵名(預設同 $key)
* @return array 分組後的關聯陣列 [鍵值 => [元素1, 元素2, ...]]
*/
function combine_same_val($array, $start, $key, $newkey = null) {
static $result = [];
$newkey = $newkey ?? $key;
foreach ($array as $k => $v) {
if (!isset($v[$key])) continue; // 防禦性檢查
if ($v[$key] == $start) {
$result[$v[$newkey]][] = $v;
unset($array[$k]);
}
}
// 重新索引並遞歸處理剩餘元素
if (count($array) > 0) {
$array = array_values($array); // 重置索引
combine_same_val($array, $array[0][$key], $key, $newkey);
}
return $result;
}
?>
<?php
$data = [
['id' => 1, 'category' => 'fruit', 'name' => 'Apple', 'price' => 50],
['id' => 2, 'category' => 'fruit', 'name' => 'Banana', 'price' => 30],
['id' => 3, 'category' => 'veg', 'name' => 'Carrot', 'price' => 20],
['id' => 4, 'category' => 'fruit', 'name' => 'Orange', 'price' => 40],
['id' => 5, 'category' => 'veg', 'name' => 'Spinach','price' => 25],
];
$grouped = combine_same_val($data, $data[0]['category'], 'category');
print_r($grouped);
/* 輸出:
Array
(
[fruit] => Array
(
[0] => Array ( [id]=>1 [category]=>fruit [name]=>Apple [price]=>50 )
[1] => Array ( [id]=>2 [category]=>fruit [name]=>Banana [price]=>30 )
[2] => Array ( [id]=>4 [category]=>fruit [name]=>Orange [price]=>40 )
)
[veg] => Array
(
[0] => Array ( [id]=>3 [category]=>veg [name]=>Carrot [price]=>20 )
[1] => Array ( [id]=>5 [category]=>veg [name]=>Spinach [price]=>25 )
)
)
*/
?>
| 指標 | 表現 |
|---|---|
| 時間複雜度 | O(n²) —— 每次遞歸遍歷剩餘陣列 |
| 空間複雜度 | O(n) —— 靜態變數累積結果 |
| 適用規模 | 中小型陣列(< 10,000 筆) |
| 穩定性 | 保持原陣列相對順序 |
<?php
function group_by_key_iterative($array, $key, $newkey = null) {
$newkey = $newkey ?? $key;
$result = [];
foreach ($array as $item) {
if (!isset($item[$key])) continue;
$groupKey = $item[$newkey];
$result[$groupKey][] = $item;
}
return $result;
}
// 使用方式相同,效能大幅提升
$grouped = group_by_key_iterative($data, 'category');
?>
<?php
// array_column + array_reduce 一行搞定
$grouped = array_reduce($data, function($carry, $item) {
$carry[$item['category']][] = $item;
return $carry;
}, []);
// 或使用 Laravel Collection(若有引入)
// collect($data)->groupBy('category')->toArray();
?>
isset($v[$key]) 判斷$result = [] 或改用非靜態版本GROUP BY