从JavaScript数组中移除重复值

从JavaScript数组中移除重复值

技术背景

在JavaScript开发中,经常会遇到需要从数组中移除重复值的场景。例如,处理用户输入的数据、合并多个数组后去除重复元素等。不同的去重方法在性能、适用场景和代码简洁性上有所差异。

实现步骤

1. 使用Set和扩展运算符

Set是ES6引入的新的数据结构,它类似于数组,但成员的值都是唯一的。结合扩展运算符...可以很方便地将Set转换为数组。

1
const uniq = [...new Set(array)];

2. 使用filter和indexOf方法

通过filter方法过滤出数组中首次出现的元素。

1
2
3
const uniqueArray = a.filter(function(item, pos) {
return a.indexOf(item) == pos;
});

或者使用ES6箭头函数的简写形式:

1
const uniqueArray = a.filter((item, pos) => a.indexOf(item) === pos);

3. 使用哈希表

利用对象作为哈希表来记录元素是否已经出现过。

1
2
3
4
5
6
function uniq(a) {
var seen = {};
return a.filter(function(item) {
return seen.hasOwnProperty(item) ? false : (seen[item] = true);
});
}

4. 通用解决方案

结合哈希查找和线性搜索,对基本类型使用哈希查找,对对象使用线性搜索。

1
2
3
4
5
6
7
8
9
10
11
function uniq(a) {
var prims = {"boolean":{}, "number":{}, "string":{}}, objs = [];

return a.filter(function(item) {
var type = typeof item;
if(type in prims)
return prims[type].hasOwnProperty(item) ? false : (prims[type][item] = true);
else
return objs.indexOf(item) >= 0 ? false : objs.push(item);
});
}

5. 先排序再去重

先对数组进行排序,然后过滤掉与前一个元素相同的元素。

1
2
3
4
5
function uniq(a) {
return a.sort().filter(function(item, pos, ary) {
return !pos || item != ary[pos - 1];
});
}

6. 根据特定条件去重

通过传递一个回调函数来指定去重的条件。

1
2
3
4
5
6
7
function uniqBy(a, key) {
var seen = {};
return a.filter(function(item) {
var k = key(item);
return seen.hasOwnProperty(k) ? false : (seen[k] = true);
})
}

核心代码

以下是几种常见方法的核心代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 使用Set和扩展运算符
const array = [1, 2, 2, 3, 4, 4, 5];
const uniq = [...new Set(array)];
console.log(uniq); // [1, 2, 3, 4, 5]

// 使用filter和indexOf方法
const uniqueArray = array.filter((item, pos) => array.indexOf(item) === pos);
console.log(uniqueArray); // [1, 2, 3, 4, 5]

// 使用哈希表
function uniqWithHash(a) {
var seen = {};
return a.filter(function(item) {
return seen.hasOwnProperty(item) ? false : (seen[item] = true);
});
}
console.log(uniqWithHash(array)); // [1, 2, 3, 4, 5]

最佳实践

  • 对于基本类型数组:优先使用Set和扩展运算符的方法,代码简洁且性能较好。
1
2
3
const numbers = [1, 2, 2, 3, 3, 4];
const uniqueNumbers = [...new Set(numbers)];
console.log(uniqueNumbers); // [1, 2, 3, 4]
  • 对于需要自定义去重条件的数组:使用uniqBy函数,通过传递合适的回调函数来实现。
1
2
3
4
5
6
7
const objects = [
{ id: 1, name: 'John' },
{ id: 2, name: 'Jane' },
{ id: 1, name: 'John' }
];
const uniqueObjects = uniqBy(objects, obj => obj.id);
console.log(uniqueObjects); // [ { id: 1, name: 'John' }, { id: 2, name: 'Jane' } ]

常见问题

1. 哈希表方法无法区分数字和字符串

由于JavaScript中哈希键只能是字符串或符号,哈希表方法无法区分数字和“数字字符串”。例如,uniq([1, "1"])会返回[1]

2. 排序去重方法对对象无效

排序去重方法依赖于元素的比较,对于对象来说,由于对象的比较规则不同,该方法无法正确去重。

3. 性能问题

使用filterindexOf方法的时间复杂度为$O(n^2)$,对于大数组来说性能较差。可以使用哈希表或Set方法将时间复杂度降低到$O(n)$。


从JavaScript数组中移除重复值
https://119291.xyz/posts/2025-05-14.remove-duplicate-values-from-js-array/
作者
ww
发布于
2025年5月14日
许可协议