JavaScript 数组去重方法汇总:从 Set 到 reduce 7种方案
Introduction
数组去重是 JavaScript 开发中的常见需求,本文汇总 7 种去重方法,从 ES6 Set(最简洁)到 reduce(最灵活),覆盖不同场景的优缺点和性能对比。
方法1:Set(ES6,推荐)
/* Set 是一种不允许重复值的数据结构 */
var arr = [1, 2, 2, 3, 3, 3, 'a', 'a'];
var unique = [...new Set(arr)];
// [1, 2, 3, 'a']
/* 或使用 Array.from */
var unique2 = Array.from(new Set(arr));
/* 优点:语法简洁,性能好 */
/* 缺点:无法去除 {}、[] 等引用类型重复(因为引用不相等)*/
方法2:filter + indexOf
var unique = arr.filter(function(item, index) {
return arr.indexOf(item) === index;
});
/* 保留第一次出现的位置,后续重复项被过滤 */
方法3:reduce + includes
var unique = arr.reduce(function(acc, item) {
if (!acc.includes(item)) {
acc.push(item);
}
return acc;
}, []);
console.log(unique);
方法4:对象键值对(处理引用类型)
/* 只能处理原始值(数字、字符串)*/
var unique = Object.keys(
arr.reduce(function(obj, item) {
obj[item] = true;
return obj;
}, {})
); // 返回字符串键,需要 Number() 转换
/* 改进版:处理数字和字符串混合 */
var unique = arr.filter(function(item) {
return typeof item + '|' + item;
}).filter(function(item, index, self) {
return self.indexOf(item) === index;
});
方法5:排序后相邻比较
var sorted = arr.slice().sort(function(a, b) { return a - b; });
var unique = sorted.filter(function(item, index) {
return item !== sorted[index - 1];
});
/* 注意:sort 是字符串排序,需要自定义比较函数处理数字 */
性能对比
/* 10万条数据下测试结果(从快到慢):*/
/* 1. Set:最快,O(n) 复杂度 */
/* 2. Object 键值对:O(n) */
/* 3. filter + indexOf:O(n^2),但代码最简洁 */
/* 4. reduce + includes:O(n^2) */
常见问题
- NaN 去重:Set 能正确处理 NaN(NaN === NaN 为 false),但 indexOf 方法不能(因为 NaN !== NaN)。
- 引用类型去重:Set 无法去除 {a:1} 和 {a:1},因为引用地址不同。需要手动用 JSON.stringify 或哈希函数处理。
- 大量数据:对于百万级数据,Set 是唯一合理选择。
延伸阅读
- MDN Set:MDN Set