
本文介绍一种高效方法,将对象数组按 type 字段的连续相同值进行分组,仅合并相邻重复项(而非全局去重),最终生成包含 type 和对应 values 数组的结构化结果。
本文介绍一种高效方法,将对象数组按 `type` 字段的**连续相同值**进行分组,仅合并相邻重复项(而非全局去重),最终生成包含 `type` 和对应 `values` 数组的结构化结果。
在实际业务场景中(如时间线渲染、日志归并、状态序列聚合),我们常需识别“连续相同类型”的数据块——例如同一用户连续多段 A 类操作、中间被 B 类中断后又恢复 A 类,应视为两个独立的 A 组。这与普通 groupBy 或 Set 去重有本质区别:它依赖位置连续性,而非字段唯一性。
核心思路是遍历数组,动态维护一个结果集,并始终检查当前元素是否与上一组的 type 相同。若相同,则追加到最后一组的 values 中;否则新建一组。
以下是推荐实现(兼容现代浏览器及 Node.js):
const data = [
{ object: 1, start: "2018-07-08", end: "2018-12-31", type: "A", user: "ABCD" },
{ object: 2, start: "2018-12-31", end: "2019-06-26", type: "A", user: "ABCD" },
{ object: 3, start: "2019-06-26", end: "2019-12-31", type: "B", user: "PQRS" },
{ object: 4, start: "2019-12-31", end: "2020-06-31", type: "B", user: "PQRS" },
{ object: 5, start: "2021-12-31", end: "2022-12-31", type: "A", user: "ABCD" },
{ object: 6, start: "2012-12-31", end: "2022-06-26", type: "A", user: "ABCD" },
{ object: 7, start: "2022-06-26", end: "2022-12-31", type: "A", user: "ABCD" },
{ object: 8, start: "2022-12-31", end: "2023-06-26", type: "A", user: "ABCD" }
];
const grouped = data.reduce((result, item) => {
// 检查是否可追加到前一组(存在且 type 匹配)
if (result.length > 0 && result.at(-1).type === item.type) {
result.at(-1).values.push(item);
} else {
// 新建分组
result.push({ type: item.type, values: [item] });
}
return result;
}, []);
console.log(grouped);
// 输出符合预期的三组:A(2项) → B(2项) → A(4项)✅ 关键特性说明:
- 使用
Array.prototype.at(-1)安全获取最后一项(替代result[result.length - 1],更语义化); - 利用
reduce单次遍历完成分组,时间复杂度 O(n),空间复杂度 O(n); - 不修改原数组,纯函数式风格,便于测试与复用;
- 兼容
null/undefined边界情况(因result.length > 0提前校验)。
⚠️ 注意事项:
- 此逻辑严格依赖原始数组顺序。若数据未按时间或业务逻辑排序,请先调用
sort()预处理; -
at()方法在 IE 中不可用,如需兼容旧环境,可替换为result[result.length - 1]并增加空数组判断; - 若需进一步聚合(如合并时间区间),应在分组后对每个
values子数组单独处理。
该方案简洁、健壮且易于理解,是处理“连续相同类型分组”问题的标准实践。

















