
本文介绍一种高效方法,将对象数组按 type 字段的连续相同值进行分组,即仅当相邻元素 type 相同时才合并为同一组,而非全局去重;适用于时间序列、状态流等需保持原始顺序与连续性的真实业务场景。
本文介绍一种高效方法,将对象数组按 `type` 字段的**连续相同值**进行分组,即仅当相邻元素 `type` 相同时才合并为同一组,而非全局去重;适用于时间序列、状态流等需保持原始顺序与连续性的真实业务场景。
在实际开发中(如用户行为日志聚合、设备状态变迁分段、合同周期归并等),我们常需将一组有序对象按连续相同的属性值切分为多个逻辑块——这不同于简单的 Array.from(new Set(...)) 全局去重,而是强调“位置连续性”。例如,数组中出现 ["A", "A", "B", "B", "A", "A", "A"] 时,应拆分为三组:[A,A]、[B,B]、[A,A,A],而非合并所有 A 为一组。
核心思路是:遍历数组,维护一个结果集 result,每次检查当前对象的 type 是否与上一组末尾的 type 相同。若相同,则追加到该组的 values 数组中;否则新建一组 { type, values: [current] }。
以下是推荐的简洁、健壮且可读性强的实现方案(使用 Array.prototype.reduce):
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, current) => {
// 检查 result 中最后一项是否存在,且其 type 与当前一致
const lastGroup = result.at(-1);
if (lastGroup && lastGroup.type === current.type) {
lastGroup.values.push(current);
} else {
result.push({ type: current.type, values: [current] });
}
return result;
}, []);
console.log(grouped);
// 输出符合预期的三组结构:A(2项) → B(2项) → A(4项)
✅ 关键优势说明:
- ✅ 语义清晰:
result.at(-1)明确表达“取最后一组”,比result[result.length - 1]更现代、安全; - ✅ 空数组兼容:
result.at(-1)在空数组时返回undefined,配合&&短路逻辑天然规避报错; - ✅ 零依赖:纯原生 JavaScript,无需引入 Lodash 或其他工具库;
- ✅ 可扩展性强:如需额外聚合字段(如合并
start/end时间范围),可在push或push后直接操作values数组。
⚠️ 注意事项:
- 该算法严格依赖输入数组的原始顺序。若数据本身无序,请先按业务逻辑(如
start时间戳)排序,再执行分组; -
at(-1)在旧版浏览器(如 IE)中不支持,如需兼容,可用result[result.length - 1] || null替代; - 若
type字段可能为null/undefined,建议增加空值校验:lastGroup?.type === current.type。
总结:这种“连续分组”模式是处理时序型、状态流型数据的基础能力。掌握 reduce + at(-1) 的组合用法,既能写出简洁可靠的代码,也便于后续扩展(如添加组内统计、边界校验等),是前端工程师处理结构化列表数据的重要实践技能。










