
本文介绍一种时间复杂度为 O(n) 的简洁方法,通过 filter() 配合索引比较,仅移除紧邻重复项(即连续相同元素保留首个),不改变非相邻重复元素的出现顺序。
本文介绍一种时间复杂度为 o(n) 的简洁方法,通过 `filter()` 配合索引比较,仅移除**紧邻重复项**(即连续相同元素保留首个),不改变非相邻重复元素的出现顺序。
在实际开发中,我们常需对数组做“去重”处理,但需注意:去重 ≠ 去相邻重复。例如,[1, 2, 2, 3, 3, 1, 1, 4] 中的 1 出现了多次,但它们被其他元素隔开——这类非相邻重复应予以保留;真正需要剔除的,只是像 2, 2 或 3, 3 这样物理位置连续、值完全相同的相邻对。
最直接且高效的解法是使用 Array.prototype.filter(),结合当前元素与前一项的比较:
const items = [1, 2, 2, 3, 3, 1, 1, 4, 5, 5, 4, 4, 4, 6, 2]; const deduped = items.filter((value, index) => value !== items[index - 1]); console.log(deduped); // [1, 2, 3, 1, 4, 5, 4, 6, 2]
✅ 原理说明:
- index === 0 时,items[-1] 为 undefined,value !== undefined 恒为 true,因此首项必被保留;
- 对于 index > 0,仅当当前值不等于前一项时才保留,从而跳过所有紧随其前项出现的重复值。
⚠️ 注意事项:
- 该方法不修改原数组,返回全新数组,符合函数式编程习惯;
- 时间复杂度严格为 O(n),空间复杂度为 O(n)(输出数组);
- 适用于任意可比较类型(数字、字符串、布尔值等),但不适用于引用类型(如对象、数组)的深度相等判断——若需处理对象数组,应改用 JSON.stringify() 或自定义比较逻辑;
- 不依赖外部库,原生 JavaScript 即可运行,兼容性良好(ES5+)。
? 扩展思路:若需支持自定义相等判定(如忽略大小写、浮点误差容错等),可将比较逻辑封装为高阶函数:
const removeConsecutiveDuplicates = (arr, isEqual = (a, b) => a === b) => {
return arr.filter((val, i) => i === 0 || !isEqual(val, arr[i - 1]));
};
// 示例:忽略字符串大小写
const words = ['a', 'A', 'b', 'B', 'b', 'c'];
const uniqueWords = removeConsecutiveDuplicates(words, (a, b) => a.toLowerCase() === b.toLowerCase());
// → ['a', 'b', 'b', 'c'] (注意:'A' 被 'a' 过滤,但后续 'b' 和 'B' 视为相同,故第二个 'b' 保留)总之,filter + 索引比较是解决“移除相邻重复项”问题的最优实践:简洁、高效、可读性强,应作为标准工具纳入日常开发工具箱。

















