js判断数组中重复元素并找出_面试中常遇见的数组去重

导读

JS数组去重是面试中并不少见的问题,听起来很简单,当你兴高采烈地回答了你的方法之后,你以为这道题就结束了吗?No,一般来说,面试官会继续问你“除了你刚刚说的方法,还有其他更好的方法吗?”,这时的你就需要了解多几种JS数组去重的方法了。

下面我们一起来学习JS中有哪些去重方法。

01

双重for循环

循环数组,拿前一个数据和后面的数据做对比,与后面相同的就删除。

//方法1const unique = arr => {  if(!(arr instanceof Array) || arr.length == 0){    console.log('数组数据异常');    return;  }  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--;      }    }  }  return arr;}

测试数据:

let arr = [1,1,false,false,true,true,null,null,undefined,undefined,NaN,NaN,{},{},'a','a'];

测试结果

767653eeb223c51514edf32e68b2a826.png

在结果中可以看出,部分相同的数据都已经被去掉了,但是true、NaN、{}这三个是没有去除的。应该是“==”判断的问题。

可以来看看NaN的情况:

a82d59e1b3a455435e8e348c9ab4eb96.png

 两个NaN对比,居然是个false,难怪没有去重成功。其他应该也是相对如此的。

02

单个for循环和indexOf

遍历原数组,将每个元素插入到新数组中。插入前先判断新数组中是否存在改元素。利用数组的indexOf方法来查重,有就返回元素在数组中的下标,不存在就返回-1。

const unique = arr => {   .....  let arr1 = [];// 新建一个数组来存放arr中的元素  for(let i = 0; i < arr.length; i++){      if(arr1.indexOf(arr[i]) == -1){          arr1.push(arr[i]);      }  }  return arr1;}

测试数据

let arr = [1,1,false,false,true,true,null,null,undefined,undefined,NaN,NaN,{},{},'a','a'];

测试结果

1d9a24182c50eafad78d5be5f56d6d1a.png

看来这个对true去重有作用了呀,但是NaN、{}还是不起作用。

03

单个for循环和includes

这个跟第二个差不多,不同的是重复判断用的是数组的includes方法,它返回是Boolean类型,如果包含某个元素就返回true,反之false。

const unique = arr => {  .....  let arr1 = [];// 新建一个数组来存放arr中的元素  for(let i = 0; i < arr.length; i++){      if(!arr1.includes(arr[i])){          arr1.push(arr[i]);      }  }  return arr1;}

测试数据

let arr = [1,1,false,false,true,true,null,null,undefined,undefined,NaN,NaN,{},{},'a','a'];

测试结果

a0659e68fee7ca952de8aa35d6f61833.png

这次比前两次好了很多,能判断NaN了。

04

单个for循环和sort

先用sort方法对数组进行排序,然后对比相邻两个元素是否相等,做去重处理。

const unique = arr => {   .....  arr = arr.sort();  let arr1 = [arr[0]];  for(let i = 1;i < arr.length;i++){      if(arr[i] !== arr[i-1]){          arr1.push(arr[i]);      }  }  return arr1;}

测试数据

let arr = [1,1,false,false,true,true,null,null,undefined,undefined,NaN,NaN,{},{},'a','a'];

测试结果

d16d820b709e39291f53ad339b252989.png

效果还是很好的嘛。

05

ES6的Set集合

Set集合作为ES6新加入的数据结构,存储类似于数组,但是里面的元素是不能重复的。我们可以先将数组转成Set集合,去重之后,再转为数组输出。

const unique = arr => { .....  return Array.from(new Set(arr))}

Array.from()方法就是将一个类数组对象或者可遍历对象转换成一个真正的数组,不过它也是ES6的新特性。

测试数据

let arr = [1,1,false,false,true,true,null,null,undefined,undefined,NaN,NaN,{},{},'a','a'];

测试结果

f34b0e2fcdf5314b82b36fbaf9a0bd47.png

看来效果还是很不错的啊,除了 {} 不能去重外,其他都完成了。

06

数组中的filter函数

filter()会创建一个新数组,循环对数组中的元素调用callback函数, 如果返回true 保留,如果返回false 过滤掉,  返回新数组,老数组不变。

const unique = arr => {  return arr.filter((item,index) => {    return arr.indexOf(item) === index;  });}

测试数据

let arr = [1,1,false,false,true,true,null,null,undefined,undefined,NaN,NaN,{},{},'a','a'];

测试结果

c810b65496b79a271233f2a06a701458.png

这个方法也是除了 {} 无法去重外,其他都可以成功了。

07

ES6中的Map对象

Map作为ES6的一种新型数据结构,类似json,用键值对方式存储数据。Map中有has()方法,返回一个Boolean类型,来表明Map中是否存在指定元素。

const unique = arr => {  .....  let map = new Map();  let arr1 = []  for (let i = 0; i < arr.length; i++) {      if (map.has(arr[i])) {      // 判断是否存在该key值          map.set(arr[i], true);      }      else {          map.set(arr[i], false);          arr1.push(arr[i]);      }  }  return arr1;}

测试数据

let arr = [1,1,false,false,true,true,null,null,undefined,undefined,NaN,NaN,{},{},'a','a'];

测试结果

c3afb04145ed2d88aca539d069c79391.png

 也是除了{}去不了重之外,其他都正常。

08

递归

这种方法其实跟第一种方法差不多,通过循环判断前一个元素和后面元素是否相同来查重。不过要求掌握递归算法的。

const unique = arr => {  .....  let arr1 = arr;  let len = arr1.length;  function loop(index){    if(index >= 1){      if(arr1[index] === arr1[index-1] ){          arr1.splice(index,1);      }      loop(index - 1);  // 递归loop,然后数组去重    }  }  loop(len-1);  return arr1;}

测试数据

let arr = [1,1,false,false,true,true,null,null,undefined,undefined,NaN,NaN,{},{},'a','a'];

测试结果

f0a6c3b1835a2410155ffb8f48648c2b.png

除了NaN和{}无法去重外,其他都没问题。

上面的方法都能解决日常开发中的大部分去重问题,但都不能解决 {} 去重问题,难道就真的没办法了吗?

对象是永不相等的,在用 === 号的情况下,因为它们属于引用类型,在三等符号的情况下判断是内存地址了,当且仅当它们引用同一个基对象时,它们才相等。

09

ES6的Map和Set

其实可以将对象转换成字符串,然后让字符串对比,就可以做到去重的效果。

const unique = arr => {  const map = new Map()  return arr.filter( item => !map.has(JSON.stringify(item)) && map.set(JSON.stringify(item), 1));}

测试数据1

let json = [{},{}];

测试结果1

9800909d9bac4b379f1125acadefe4dd.png

 测试数据2

let json2 = [{a: 1, b: 2}, {a: 1, b: 2}];

测试结果2

4072625b184b4a8791fe4b56863b451e.png

通过上面的方法也就很好的解决了 对象 相等的问题,其实知道原理之后,用for循环也是可以解决的,但是,最近在学ES6,顺便装一下13。

上面就是这篇的全部内容了。

得到了再失去,总比从来就没有得到更伤人。

--《追风筝的人》

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值