
本文介绍使用 JavaScript reduce() 方法高效地将对象数组按 category 属性分组,生成包含 category 字段和 data 子数组的新结构,兼顾可读性与性能,适用于大规模数据场景。
本文介绍使用 javascript `reduce()` 方法高效地将对象数组按 `category` 属性分组,生成包含 `category` 字段和 `data` 子数组的新结构,兼顾可读性与性能,适用于大规模数据场景。
在实际开发中,常需将扁平的对象数组(如车辆列表)按某一字段(如 category)聚类,转换为“分类容器 + 数据集合”的嵌套结构。这种转换既便于前端渲染(如分标签页、折叠面板),也利于后续统计或筛选。最直观的思路是先提取唯一分类值再二次遍历,但该方式需两次循环,时间复杂度为 O(2n),且逻辑冗余。
更优解是使用 单次遍历 + reduce() —— 利用累加器(accumulator)动态维护分组结果。核心策略如下:
- 初始化空数组作为 reduce 的初始值;
- 每次迭代时,用 find() 检查累加器中是否已存在同名 category 对象;
- 若存在,直接 push() 当前车辆到其 data 数组;
- 若不存在,则新建 { category, data: [car] } 对象并推入累加器;
- 最终返回累加器即为目标结构。
以下是完整实现代码:
const CARS = [
{make: "skoda", model: "kodiaq", color: "light-blue", id: "1002", category: "A"},
{make: "skoda", model: "karoq", color: "green", id: "1008", category: "B"},
{make: "renault", model: "clio", color: "grey", id: "1006", category: "A"},
{make: "renault", model: "kangoo", color: "white", id: "1042", category: "C"},
{make: "mazda", model: "cx3", color: "red", id: "1022", category: "C"},
{make: "mazda", model: "cx30", color: "orange", id: "1106", category: "D"},
{make: "ford", model: "explorer", color: "grey", id: "1162", category: "B"},
{make: "ford", model: "edge", color: "red", id: "1862", category: "A"}
];
const NEW_CARS = CARS.reduce((acc, car) => {
const existingGroup = acc.find(group => group.category === car.category);
if (existingGroup) {
existingGroup.data.push(car);
} else {
acc.push({ category: car.category, data: [car] });
}
return acc;
}, []);
console.log(NEW_CARS);
✅ 性能说明:尽管 find() 在内部也是遍历,但因分组数(类别数)通常远小于总数据量(如本例仅 4 类 vs 8 条),实际时间复杂度趋近于 O(n × k),其中 k 是唯一分类数,显著优于双循环方案。若数据量极大(如 >10 万条)且分类数较多,可进一步优化为哈希映射(Map)加速查找:
// 进阶优化:O(1) 查找,适合超大数据集
const NEW_CARS_OPTIMIZED = Array.from(
CARS.reduce((map, car) => {
const group = map.get(car.category) || { category: car.category, data: [] };
group.data.push(car);
map.set(car.category, group);
return map;
}, new Map()).values()
);
⚠️ 注意事项:
- 原始数组不应被修改;reduce 是纯函数式操作,安全可靠;
- 确保 category 字段始终为字符串或可安全比较的原始类型;
- 若需保持分组顺序与首次出现顺序一致(如本例),当前方案天然满足;若需按字母序排列,最后对 NEW_CARS 调用 sort((a, b) => a.category.localeCompare(b.category)) 即可。
该方法简洁、健壮、易于理解,是 JavaScript 中数组分组重构的经典实践。











