javaScript去重的11种方法

前言

去重是开发和面试中经常遇到的问题,下面是总结的 11 种去重方法

方法

示例数组

var arr = [1, 2, 4, 5, 5, 2, 1, 1, 4, 6]

set + 解构赋值

这种方法利用了 set 成员唯一的特征和扩展运算符方法实现

function fn1() {
           return ([...new Set(arr)]);
       }
       console.log(fn1());

forEach 循环 + indexOf

先使用 foreach 循环取到每一个元素,在这里也可以改成 for 循环的写法道理是一样的,取到每一个元素后取这个元素的 index 和循环中 index 比较是否一样,一样则 push()

function fn2() {
           let temp = []
           arr.forEach((item, index) => {
               arr.indexOf(item) == index ? temp.push(item) : null
           })
           return temp
       }
       console.log(fn2());

filter 过滤

和上一种方法思路差不多,filter 相当于上面的步骤合并到一个方法中实现

function fn3() {
           let temp = arr.filter((item, index) => {
               return arr.indexOf(item) == index
           })
           return temp
       }
       console.log(fn3());

对象键值唯一性

对象的键值因为具有唯一性,所以可以将数组成员作为 key 保存起来,在数组全部循环过一次后,再循环取出对象的 key 添加到一个空白数组中,但是这种方法会导致取出的数组成员数据类型全部转换为文本类型

function fn4() {
           let obj = {}
           let temp = []
           arr.forEach((item, index) => {
               obj[item] = index //这一步赋值value其实没有必要,因为最后使用不到
           })
           for (const key in obj) {
               temp.push(key)
           }
           return temp
       }
       console.log(fn4());

双重 for 循环

外循环的作用是取到每一个元素,内循环的作用是将外循环取到的元素和其余的元素做对比,如果能取到一样的将后一个删除,要注意的是删除的话需要将内循环的计数 - 1,因为数组的长度也 - 1 了。

function fn5() {
           let temp = arr
           for (let i = 0; i < temp.length; i++) {
               for (let j = i + 1; j < temp.length; j++) {
                   if (temp[i] === temp[j]) {
                       temp.splice(j, 1)
                       j--
                   }
               }
           }
           return temp
       }
       console.log(fn5());

indexOf + lastIndexOf

这种方法的思路是如果一个元素查找她的索引,从前获得和从后获得的索引一样,则必然是唯一的,如果不一样说明有重复,删除最后一个并将计数 i-1。

function fn6(){
           for(let i =0;i<arr.length;i++){
               if(arr.indexOf(i)!=arr.lastIndexOf(i)){
                   arr.splice(arr.lastIndexOf(i),1)
                   i--
               }
           }
           return arr
       }
       console.log(fn6());

sort + 循环

思路是先将数组的内容按照大小排序,然后从第一开始和后一个进行对比,如果一样说明是重复的,将重复的删除并计数 - 1。

function fn7() {
           let temp = arr.sort((a, b) => {
               return a - b
           })
           for (let i = 0; i < temp.length; i++) {
               if (temp[i] === temp[i + 1]) {
                   temp.splice(i + 1, 1)
                   i--
               }
           }
           return temp
       }
       console.log(fn7());

includes + 循环

思路是先创建一个新数组,然后循环取到每一个元素,如果该元素不在新数组中,就将其添加进去。

function fn8() {
           let temp = []
           for (let i = 0; i < arr.length; i++) {
               if (!temp.includes(arr[i])) {
                   temp.push(arr[i])
               }
           }
           return temp
       }
       console.log(fn8());

Map

Map 是 ES6 中特性,是一种字典的数据结构,和对象一样也具有 key 的唯一性

  • map.set 设置 map 的 key
  • map.has 检测是否含有指定的 key,返回一个布尔值
function fn9() {
           let map = new Map();
           let temp = [] 
           for (let i = 0; i < arr.length; i++) {
               if (!map.has(arr[i])) { //如果键值不存在,则写入这个键值并添加到数组
                   map.set(arr[i], false);
                   temp.push(arr[i]);
               } 
           }
           return temp;
       }
       console.log(fn9());

递归

这个方法和 sort 方法也许相似,先使用 sort 排序,但是是使用递归的思路从后到前删除相同的元素

function fn10() {
           let len = arr.length;
           let temp = arr.sort(function (a, b) {
               return a - b;
           });
           function loop(index) {
               if (index >= 1) {
                   if (temp[index] === temp[index - 1]) {
                       temp.splice(index, 1);
                   }
                   loop(index - 1)
               }
           }
           loop(len - 1);
           return temp;
       }
       console.log(fn10());

Reduce

reduce 的数组的累加器方法,在本例中 reduce 的第一个参数是一个函数,用来处理每一个元素,第二个参数是一个空数组作为容器,reduce 的循环开始,空数组会被带入 prev,判断 prev 中是否含有当前处理的元素 item,如果已经有了就不做处理,如果没有就将 prev 和 item 合并为一个数组,处理完毕后这个数组会被返回给 reduce 作为下一轮处理的第二个参数,依次循环,最后得到的就是去重后的数组

function fn11() {
           return arr.reduce((prev, item) => {
               return prev.includes(item) ? prev : [...prev, item]
           }, []);
       }
       console.log(fn11());

总结

数组的去重方法有很多,在使用的时候需要根据自己的需求去选择,比如使用了 sort 的方法的去重只能使用在纯数字数组中,而对象键值去重数组后数组成员都是纯字符串等等。本篇只是简单的方法总结,还有一些没有举例,重点是解决问题思路

posted @ 2022-06-29 13:36  chenSee  阅读(3456)  评论(0编辑  收藏  举报