> 文章列表 > 浅理解JavaScript数组去重的方法(划重点),当面试官问如何实现数组去重时,你可以这样做...

浅理解JavaScript数组去重的方法(划重点),当面试官问如何实现数组去重时,你可以这样做...

浅理解JavaScript数组去重的方法(划重点),当面试官问如何实现数组去重时,你可以这样做...

文章目录

  • 📋前言
  • 🎯什么是数组去重,运用场景是什么?
  • 🎯常用的数组去重方法
    • 🧩使用 Set 对象
    • 🧩使用 Object(对象、基于Hash哈希表) 或 Map
    • 🧩使用 filter 方法与 indexOf 方法
  • 🎯其他方法
    • 🧩使用 reduce 方法
    • 🧩使用递归方法
    • 🧩使用 ES6 中的 Symbol 数据类型
    • 🧩使用 hasOwnProperty 方法
    • 🧩使用 lodash 库
  • 📝最后

在这里插入图片描述

📋前言

好久没写面试题的文章了,今天这篇文章讲一讲一个常见的面试题。在前端开发岗位的面试过程中,我们可能或多或少会提及数组这个知识点,对于数组的相关操作也是一个经常提及的技术点,其中数组去重是面试中非常常见的一个问题,无论是手写还是口述,我们都要有清晰的逻辑和思路去面对这个问题,因此这篇文章我们来浅理解在JavaScript中如何实现数组去重,让你在面试无压力回答面试官。


🎯什么是数组去重,运用场景是什么?

数组去重就是将一个数组中重复的元素去掉,只保留一个或不保留。在实际开发中,数组去重非常重要,它可以提高代码执行效率,减少内存开销,并且使数据更加规范化和易于处理。这个过程可以使用多种方法来实现,具体取决于需求和场景。

在实际开发中,数组去重常常用于以下场景:

  • 数据展示
    • 在一些数据展示的场景中,我们通常需要从后台获取到一个数组类型的数据,并将其渲染到页面上。如果数组中存在重复项,则会影响数据的展示效果。因此,我们通常需要在渲染之前使用数组去重方法对数据进行处理,以提高数据展示的质量和效率。
  • 数据统计
    • 在进行数据统计时,通常需要对数组中的元素进行去重操作,以减少重复计算,提高计算效率。例如,在进行 UV 统计时,我们需要对访客 IP 进行去重操作,以得到准确的 UV 计数结果。
    • ❗补充:UV 是 Unique Visitor(独立访客)的简称,指访问某个网站或页面的不同访客数量。UV 统计是对网站访问情况进行统计的一种方法,用于分析网站流量、用户行为等数据。
  • 表单验证
    • 在表单验证过程中,我们需要对用户输入的内容进行校验,避免用户重复提交相同的内容,这时候我们就需要对表单数据进行去重操作,以提高表单验证的准确性和稳定性。

🎯常用的数组去重方法

在实际开发中,为了提高代码执行效率和减少内存开销,我们通常采用以下几种数组去重方法。

🧩使用 Set 对象

Set 是 ES6 新增的内置对象,可以用来存储无重复值的集合。我们可以将数组转换为 Set,然后再将 Set 转换回数组即可。Set 对象的一个优点是可以快速地去除数组中的重复项。

const arr = [1, 2, 3, 3, 4, 5, 5];
const newArr = [...new Set(arr)];
console.log(newArr); // [1, 2, 3, 4, 5]

除了使用ES6中的扩展运算符加Set来实现数组去重,还可以利用 ES6 中的 from 方法。利用 ES6 中的 from 方法和 Set 数据结构,将数组转换成 Set 数据结构,再将 Set 数据结构转换回数组。

const arr = [1, 2, 3, 3, 4, 5, 5];
const newArr = Array.from(new Set(arr));
console.log(newArr); // [1, 2, 3, 4, 5]

浅理解JavaScript数组去重的方法(划重点),当面试官问如何实现数组去重时,你可以这样做...

❗ 补充
下面这段代码是实际开发中数组去重的一个案例,这段代码的作用是,把用户输入的新词条添加到历史记录的数组中,然后通过 Set 来对这个数组进行去重操作,确保渲染出来的搜索历史记录没有重复显示。
浅理解JavaScript数组去重的方法(划重点),当面试官问如何实现数组去重时,你可以这样做...

🧩使用 Object(对象、基于Hash哈希表) 或 Map

利用 Map 数据结构,遍历数组,返回一个新的数组,该数组中只包含不与前面元素重复的元素。

let arr = [1, 2, 3, 3, 4, 4, 5];
let newArr = [];
let map = new Map();
for(let i = 0; i < arr.length; i++){if(!map.has(arr[i])){map.set(arr[i], true);newArr.push(arr[i]);}
}
console.log(newArr); // [1, 2, 3, 4, 5]

这种方法跟使用对象实现的去重方法相似,只不过用的是 ES6 中新增的 Map 数据结构。Map 对象保存键值对,并且能够记住键的原始插入顺序。所以通过遍历数组将每个元素作为键存储在 Map 中,如果该元素不存在,则说明它是新的元素,此时将它添加到新建的数组 newArr 中,并在 Map 中将其添加为键。最后输出 newArr 数组即可。

接下来看看使用对象实现的去重方法。

1️⃣基于 Hash 表实现,首先创建一个空对象,遍历数组,将数组元素作为对象的键值,如果该键不存在,则添加键值对,否则不做操作。最后将对象中的所有键转换成数组即可。

let arr = [1, 2, 3, 3, 4, 4, 5];
let obj = {};
for(let i = 0; i < arr.length; i++){let value = arr[i];obj[value] = true;
}
let newArr = Object.keys(obj).map(function(item){return Number(item);
});
console.log(newArr); // [1, 2, 3, 4, 5]

它的原理是利用 JavaScript 中对象的属性唯一性,将数组中的元素作为对象的属性名,把属性值都设为 true(或任意其他值),然后再利用 Object.keys 方法获取对象的所有属性名(即数组中的不同元素),最后再利用 map 方法将属性名转换为数字类型即可。(需要注意的一点是,由于对象的属性名必须是字符串类型,因此在后续的操作中可以将它们转换为数字类型,但这并不影响数组去重的结果。)

2️⃣定义一个空对象 obj 和一个空数组 newArr。遍历原始数组 arr,对于每一个元素,执行以下操作: a. 判断 obj 中是否存在该元素,如果不存在,则将其加入 obj,并将其加入 newArr; b. 如果已经存在,则不做任何操作。遍历完所有元素后,newArr 中就存储了去重后的结果,即为 arr 去重之后的新数组。

const arr = [1, 2, 3, 3, 4, 5, 5];
const obj = {};
const newArr = [];
for(let i = 0; i < arr.length; i++) {if(!obj[arr[i]]) {obj[arr[i]] = true;newArr.push(arr[i]);}
}
console.log(newArr); // [1, 2, 3, 4, 5]

浅理解JavaScript数组去重的方法(划重点),当面试官问如何实现数组去重时,你可以这样做...

📌总结

  • 基于 Hash 表的方法仅适用于数组中元素都是基本数据类型的情况,对于包含引用类型的数组,需要使用其他方法实现去重。此外,由于 obj 对象的存在,使用这种方法会占用额外的内存空间,因此在大规模数据处理时需要考虑性能问题。
  • 相比较于基于 Hash 表的方法,使用 Map 的方法避免了对象 key 会被隐式转换成字符串的问题,同时也更加简洁明了。在大规模数据处理时,它的性能也有很好的表现。(需要注意的是,Map 是 ES6 中新增的数据结构,如果要在低版本浏览器中使用,需要进行兼容处理。)

🧩使用 filter 方法与 indexOf 方法

通过 filter 方法和 indexOf 方法来实现数组去重。对于数组中的每个元素,只保留第一个出现的元素,其他的重复元素通过 filter 方法过滤掉。

const arr = [1, 2, 3, 3, 4, 5, 5];
const newArr = arr.filter((item, index) => {return arr.indexOf(item) === index;
});
console.log(newArr); // [1, 2, 3, 4, 5]

不使用 filter 的情况下,只使用 indexOf 方法进行去重,可以通过遍历原数组 arr,对于每个元素,判断它在数组中第一次出现的位置是否等于当前位置。如果相等,则说明它是第一次出现,将其添加到新建的数组 newArr 中即可。

let arr = [1, 2, 3, 3, 4, 4, 5];
let newArr = [];
for(let i = 0; i < arr.length; i++){if(arr.indexOf(arr[i]) === i){newArr.push(arr[i]);}
}
console.log(newArr); // [1, 2, 3, 4, 5]

❗ 补充:与 indexOf 方法类似,可以用 includes 方法进行数组去重的操作,逻辑思路也非常相似,区别在于这两个方法的实质区别。

includes() 方法是 ES7 引入的新方法,该方法判断一个数组是否包含一个指定的值,如果是,则返回 true;否则,返回 false。需要注意的是,includes() 方法是区分基本数据类型和引用数据类型的,也就是说,对于引用数据类型,它们的地址不同即使它们所存储的值相同,也会被认为是不同的元素。另外,includes() 方法不返回符合条件的元素的下标,而是直接返回一个布尔值。

indexOf() 方法是 JavaScript中常用的数组方法,用于返回指定元素在数组中第一次出现的位置。与 includes() 方法不同,indexOf() 方法返回符合条件的元素的下标位置,如果没有找到,则返回 -1。

includes() 方法只接受一个参数,即要查找的元素;而 indexOf() 方法可以接受两个参数,第一个参数为要查找的元素,第二个参数为起始搜索位置的索引值。

let arr = [1, 2, 3, 3, 4, 4, 5];
let newArr = [];
for(let i = 0; i < arr.length; i++){if(!newArr.includes(arr[i])){newArr.push(arr[i]);}
}
console.log(newArr); // [1, 2, 3, 4, 5]

浅理解JavaScript数组去重的方法(划重点),当面试官问如何实现数组去重时,你可以这样做...


🎯其他方法

除了上述的这些较为常用的方法,数组去重的方法还有很多,这里就不详细介绍了,接下来简单介绍几个。

🧩使用 reduce 方法

利用数组的 reduce 方法,遍历数组,使用一个变量保存上一个已经出现过的元素,并将当前元素与该变量进行比较,若不相同则加入新的数组中。

1️⃣使用indexOf()

let arr = [1, 2, 3, 3, 4, 4, 5];
let newArr = arr.reduce((item, index) => {if(item.indexOf(index)===-1){item.push(index);}return item;
}, []);
console.log(newArr); // [1, 2, 3, 4, 5]

2️⃣使用includes()

let arr = [1, 2, 3, 3, 4, 4, 5];
let newArr = arr.reduce((item, index) => {if(!item.includes(index)){item.push(index);}return item;
}, []);
console.log(newArr); // [1, 2, 3, 4, 5]

🧩使用递归方法

递归地遍历数组并将出现在前面的元素和后面出现的相同元素删除掉。

let arr = [1, 2, 3, 3, 4, 4, 5];
for(let i = 0; i < arr.length; i++){for(let j = i + 1; j < arr.length; j++){if(arr[i] === arr[j]){arr.splice(j, 1);j--;}}
}
console.log(arr); // [1, 2, 3, 4, 5]

🧩使用 ES6 中的 Symbol 数据类型

创建一个空对象,遍历数组,将数组元素作为对象的键值,由于 Symbol 值在对象属性名上是唯一的,因此如果该键不存在,则添加该键,否则不做操作。最后将所有键转换成数组即可。

let arr = [1, 2, 3, 3, 4, 4, 5];
let obj = {};
for(let i = 0; i < arr.length; i++){let value = arr[i];obj[Symbol.for(value)] = value;
}
let newArr = Object.getOwnPropertySymbols(obj).map(function(sym){return obj[sym];
});
console.log(newArr); // [1, 2, 3, 4, 5]

🧩使用 hasOwnProperty 方法

利用 Object 对象的 hasOwnProperty 方法,利用其属性名唯一特性,遍历数组,返回一个新的数组,该数组中只包含不与前面元素重复的元素。

let arr = [1, 2, 3, 3, 4, 4, 5];
let newArr = [];
let obj = {};
for(let i = 0; i < arr.length; i++){if(!obj.hasOwnProperty(arr[i])){obj[arr[i]] = true;newArr.push(arr[i]);}
}
console.log(newArr); // [1, 2, 3, 4, 5]

🧩使用 lodash 库

lodash 库是一个 JavaScript 的实用工具库,其中包含了大量的常用函数。使用 lodash 库的 uniq 函数即可实现数组去重。

import { uniq } from 'lodash';let arr = [1, 2, 3, 3, 4, 4, 5];
let newArr = uniq(arr);
console.log(newArr); // [1, 2, 3, 4, 5]

📝最后

在开发中,数组去重非常重要,它可以提高代码执行效率,减少内存开销,并且使数据更加规范化和易于处理。数组去重的方法有很多,我们要具体问题具体分析,可以选择根据具体场景和需求,选用最适合的去重方法,多方面考虑,比如说考虑这个方法的时间复杂度、数组大小、数组是否要过滤、排序等等问题。
在这里插入图片描述