请分享你知道的数组去除重复 (remove duplicates) 方法
2022年12月21日
💎 加入 E+ 成長計畫 如果你喜歡我們的內容,歡迎加入 E+,獲得更多深入的軟體前後端內容
在数组中把重复的项目去除掉,是很常在实际工作中需要执行的操作。因此在 JavaScript 面试时,也很常会被问。这种题目通常会要当场手写,所以假如你不太确定要怎么手写去除重复,一定要在面试前多练习几次。
数组去除重复题目长什么样?
数组去除重复的面试题,通常会像下面这样,给一个数组,里面有重复的数字,并要求写一个 removeDuplicate
函式,输入是原始数组,输出是去除重复数字的数组。
const originalArr = [9,1,2,2,3,4,2,4,8,1,9]
function removeDuplicate(array){
...
}
const ans = removeDuplicate(originalArr);
console.log(ans) // [9,1,2,3,4,8]
数组去重复其实有很多种做法,以下会列出 4 种常见做法。在面试考手写题时,数组去重复有可能是单独一种题型,或者是在解手写题时一开始需要将数组进行去重复的操作。建议询问面试官题目的需求、主动跟面试官讨论期望的解法,再选择要使用哪一种解法。
四种解法
解法一:使用 Set
去重复
Set
的资料格式与用法类似于Array
,但有一特色是Set
中只能储存任何资料的唯一值,因此可以先将Array
转为Set
,此时重复的值会被移除,再将Set
转为Array
。 代码如下:
function removeDuplicate(arr) {
return Array.from(new Set(arr));
}
// 也可以利用 spread syntax 更简化代码
function removeDuplicate(arr) {
return [...new Set(arr)];
}
let arr = [1, 2, 3, 2, 3, 8];
let arrAfter = removeDuplicate(arr);
console.log(arr1After); // [1, 2, 3, 8]
解法二: filter
搭配 indexOf
此解法先用 array 的 filter 方法,搭配 indexOf 方法,只保留第一次出现的值,所以只要是第二次出现的,就会被筛掉,这能确保结果不会有重复的。 代码如下:
function removeDuplicate(arr) {
// indexOf 会回传在这个 array 等同于此值第一个 item 的 index,
// 所以如果 indexOf 回传的 index 相等于目前 filter 到的值,
// 则代表该值是第一次出现,我们保留起来,
// 反之,如果 index 不等于,则代表此 array 中前面位置已经出现过,所以就 filter 掉。
return arr.filter((item, index, array) => array.indexOf(item) === index);
}
let arr = [1, 2, 3, 2, 3, 8];
let arrAfter = removeDuplicate(arr);
console.log(arrAfter); // [1, 2, 3, 8]
解法三: 双层 for loop
双层 for loop 是一种暴力解。依序遍历整个 array,再透过第二层 for loop 找出重复的值将其移除。 代码如下:
function removeDuplicate(arr) {
// 第一层 for loop,i 从 index 0 开始,到 arr 最后
for (let i = 0, len = arr.length; i < len; i++) {
// 第二层 for loop,j 从 i + 1 开始,要检查值是否重复
for (let j = i + 1; j < len; j++) {
// 如果值重复,则透过 splice 方法将 j 位置的值从 arr 去除
if (arr[i] == arr[j]) {
arr.splice(j, 1);
// 移除重复的值之后,arr length 长度会需要减 1
len--;
// j 位置的值被移除,因此 j index 也要减 1
j--;
}
}
}
return arr;
}
let arr = [1, 2, 3, 2, 3, 8];
let arrAfter = removeDuplicate(arr);
console.log(arrAfter); // [1, 2, 3, 8]
解法四: 透过 object 或 Map 储存以遍历过的项目
我们可以透过 object 或 Map 来储存已经遍历过的项目,来找出是否已存在数组当中,如果还不在,那就放进要输出的数组;如果已经在了,就不再放入,这样一来能确保数组中没有重复的值。 代码如下:
function removeDuplicate(arr) {
let seen = {};
let newArray = [];
// 遍历过原本的数组
for (let item of arr) {
// 判断当前被遍历到的项目是否已经放入过
if (seen[item] !== true) {
newArray.push(item); // 如果还没,则放入要被输出的新数组
seen[item] = true; // 这时纪录一下这个项目已经被放入,下次就不会再被放入
}
}
return newArray;
}
let arr = [1, 2, 3, 2, 3, 8];
let arrAfter = removeDuplicate(arr);
console.log(arrAfter); // [1, 2, 3, 8]