阅读 93

数组的高级用法 (2)

前言

上篇,我们一起学些了去空值,生成随机数据和序列, 清空数组,数组浅拷贝等数组的高级用法,今天我们继续数组的奇妙之旅。

大家,动起来。

数组去重

非常主流的的Set配合数组去重。

var arr = ["苹果", "梨", 1,1,3, 3, undefined, {a: 1}]; var arr2 = Array.from(new Set(arr));  // ['苹果', '梨', 1, 3, undefined, {…}] 复制代码

咋眼一看,没问题,666。

对于引用类型,但是这个有一个很严重的问题,就是对重的定义?

 function uniqueArray(arr){     return Array.from(new Set(arr)) } var arr = [{a:1}, {a:1}]; console.log(uniqueArray(arr)); // [{a:1}, {a:1}] var obj1 = {a:1} var arr2 = [obj1, obj1]; console.log(uniqueArray(arr2));  // [{a:1}] 复制代码

从例子中可见看得出Array.from(new Set(arr))对同引用 的对象是有用的,但是对属性键和值都相同的对象却没有作用的,比如你从接口获得的数据。

有些前端就要说了,这后端做就行,我微微一笑,你看迷人不?

多义真的对引用类型去重,用Set是满足不了的,这个时候,有请Array.prototype.filter

function uniqueArray(arr = [], key){     const keyValues = new Set();     let val;     return arr.filter(obj=> {         val = obj[key];         if(keyValues.has(val)){             return false;         }         keyValues.add(val);         return true;        }) } var arr = [{a:1}, {a:1}]; console.log(uniqueArray(arr));  // [{a:1}] 复制代码

上面的原理就是通过一个唯一的键值来过滤,不错不错,看起来不错,但是要多个值才能确认唯一的项呢?

亲, 基于上面的代码,你可以的。

求交集

网上常见的是这样:

const arr1 = [0, 1, 2]  const arr2 = [3, 2, 0]  const values = [...new Set(arr1)].filter(item =>arr2 .includes(item))  console.log(values)  // [0, 2] 复制代码

不通用,我们抽象一下:

function intersectSet(arr1, arr2){     return [...new Set(arr1)].filter(item =>arr2 .includes(item)) } intersectSet(arr1, arr2) // [0, 2] 复制代码

咋眼一看,也没问题,这有两个问题:

  1. 引用类型和相同的判断

  2. 性能问题 每次includes,这个是不是有点费资源。

我们改进一波, 假设对象都是有效的对象

 // 引用类型 function intersect(arr1, arr2, key){      const map = new Map();     arr1.forEach(val=> map.set(val[key]))     return arr2.filter(val=> {         return map.has(val[key]);     }); } // 原始数据类型 function intersectBase(arr1, arr2){      const map = new Map();     arr1.forEach(val=> map.set(val))     return arr2.filter(val=> {         return map.has(val);     }); } var arr1 = [{p:0}, {p:1}, {p:2}]  var arr2 = [{p:3}, {p:2}, {p:1}]   intersect(arr1, arr2, "p"); // [{p:2, p: 1}] const arr1 = [0, 1, 2]  const arr2 = [3, 2, 0]  intersectBase(arr1,arr2 ); 复制代码

这里大家可能有人会说,这性能会高一些吗?,那我们一起测试一把。

function createData(length){         return Array.from({length}, (val, i)=> {         return ~~(Math.random()* length)     }) } var data1 = createData(10000); var data2 = createData(10000); console.time("intersectSet"); intersectSet(data1, data2); console.timeEnd("intersectSet"); console.time("intersectBase"); intersectBase(data1, data2); console.timeEnd("intersectBase"); 复制代码

数组长度intersectSet (ms)intersectBase (ms)
10000.60.2
1000051.22.7
1000004973.822.1

可以看到,数据越多,使用Set + Array.prototype.includes相对Map性能越差,这个是和数据结构挂钩的,平时可能不需要那么多注意,但是,这些基本知识还是要了解的。

小结

今天学习了数组去重和求交集。 今天你收获了吗?


作者:一花一个世界
链接:https://juejin.cn/post/7015373530757873694


文章分类
后端
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐