Set

Set 类似于数组,是一种集合的数据结构,和 Array 之间最大的区别是:

  • Set中所有的成员都是唯一的。

    可以把Set想象成是一个: 既没有重复元素,也没有顺序概念的数组。

Set 本身是一个构造函数,用来生成 Set 数据结构

const s1 = new Set();
s1.add(5)
s1.add(2).add(1).add(3).add(2).add(4)
console.log(s1);

Set 函数可接受一个可循环的数据结构(如数组、类数组、含有 iterable 接口的其他数据结构)作为参数来初始化

const s2 = new Set([1, 2, 3, 4, 2, 3, 6])
console.log(s2)

对于对象,只对键值对中的键去重,值不去重,若重复,保留后放入的

const s4 = new Set([{ "age": 17, "age": 18, "value": '张三', "value2": '张三', "name": '李刚' }, 1, 2, 3])
console.log(s4)

1.set属性及操作方法

const s2 = new Set([1, 2, 3, 4, 2, 3, 6])
console.log('========属性及操作方法============================');
console.log(s2.size); // set的长度
console.log(s2.add('123')); // 向set中添加一个值,返回set结构本身,所以可使用链式结构
console.log(s2.delete(3)); // 删除一个值,返回布尔值,表示是否删除成功
console.log(s2.has(6)); // set中是否包含某个值,返回布尔值
console.log(s2.has(3)); // set中是否包含某个值,返回布尔值
console.log(s2.clear()); // 清除所有成员,无返回值
console.log('====================================');

2.set循环的方式

const s3 = new Set(['a', 'b', 'c', 'd', '1', '2', 4, 5])
console.log('==========循环==========================');
console.log(s3);
console.log(s3.keys()); // 返回键名
console.log(s3.values()); // 返回键值
console.log(s3.entries()); // 返回所有键值对成员
console.log(s3.forEach(e => { // 遍历每一个成员
console.log(e)
}));
console.log('====================================');

set结构没有键名,只有键值(键名和键值是一个值),所以key方法和value方法的行为完全一致,entries方法返回的同时包括键名和键值,所以每次输出一个数组,它的两个成员完全相等。

3. set应用

3.1. 数组去重

let array = [1, 2, 1, 3, 4, 4, 2, 7, 8]
console.log('=====数组去重===============================');
console.log([...new Set(array)]);
console.log('====================================');

3.2 实现并集,交集

let a = new Set([1, 2, 3])
let b = new Set([2, 3, 4])
console.log('======并集/交集/差集==============================');
console.log(new Set([...a, ...b]))
console.log(new Set([...a].filter(x => b.has(x))))
console.log(new Set([...a].filter(x => !b.has(x))))
console.log('====================================');

WeakSet 结构与 Set 类似,也是不重复的值的集合。但是,它与 Set 有两个区别。

  • WeakSet 的成员只能是对象,而不能是其他类型的值。
  • WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中。
let w = new WeakSet([1, 2, 3])
let w3 = new WeakSet([{ "age": 17 }])
var obj = {}
var sin = {}
console.log('========WeakSet============================');
// console.log(w); // 报错
console.log(typeof w3);
console.log(w3.add({ "name": "张三" }));
console.log(w3.size);
// console.log(w3.keys()); // 报错
console.log(w3.add(obj))
console.log(w3.has(obj))
console.log(w3.has(sin))
console.log('====================================');

- WeakSet结构也提供了add( ) 方法,delete( ) 方法,has( )方法给开发者使用,作用与用法跟Set结构完全一致。

- WeakSet 结构不可遍历。因为它的成员都是对象的弱引用,随时被回收机制回收,成员消失。所以WeakSet 结构不会有keys( ),values( ),entries( ),forEach( )等方法和size属性。

Map

Map和set类似

Set,Map去重和数组去重的性能比较

Array.from()方法从一个类似数组或可以迭代的对象中创建一个新的数组实例

let arr1 = Array.from(new Array(100000), (x, index) => {
return index
}) let arr2 = Array.from(new Array(50000), (x, index) => {
return index + index
}) let start = new Date().getTime()
console.log('开始数组去重') function distinct(a, b) {
// 数组去重 // 方法一
// Array.filter() + indexOf
// 这个方法的思路是,将两个数组拼接为一个数组,然后使用 ES6 中的 Array.filter() 遍历数组,并结合 indexOf 来排除重复项 // let arr = a.concat(b);
// return arr.filter((item, index) => {
// return arr.indexOf(item) === index
// }) // 方法二
// 双重 for 循环
// 外层循环遍历元素,内层循环检查是否重复
// 当有重复值的时候,可以使用 push(),也可以使用 splice() // let arr = a.concat(b);
// for (let i = 0, len = arr.length; i < len; i++) {
// for (let j = i + 1; j < len; j++) {
// if (arr[i] == arr[j]) {
// arr.splice(j, 1);
// // splice 会改变数组长度,所以要将数组长度 len 和下标 j 减一
// len--;
// j--;
// }
// }
// }
// return arr // 方法三
// for...of + includes()
// 双重for循环的升级版,外层用 for...of 语句替换 for 循环,把内层循环改为 includes()
// 先创建一个空数组,当 includes() 返回 false 的时候,就将该元素 push 到空数组中
// 类似的,还可以用 indexOf() 来替代 includes() // let arr = a.concat(b)
// let result = []
// for (let i of arr) {
// !result.includes(i) && result.push(i)
// }
// return result // 方法三和方法一类似,因此时长也接近 // 方法四
// Array.sort()
// 比较相邻元素是否相等,从而排除重复项 // let arr = a.concat(b)
// arr = arr.sort()
// let result = []
// for (let i = 0; i < arr.length; i++) {
// arr[i] !== arr[i - 1] && result.push(arr[i])
// }
// return result // 方法五 Set
// new Set() set的成员具有唯一性 // return Array.from(new Set([...a, ...b])) // 方法六 Map
// 如果res中没有某个键,就设置这个键的值为1 // const arr = a.concat(b)
// const res = new Map();
// return arr.filter(item => !res.has(item) && res.set(item, 1)) } console.log('去重后的长度', distinct(arr1, arr2).length) let end = new Date().getTime()
console.log('耗时', end - start)

通过对比,set,map去重性能更好

Map,Set和数组的对比

let map = new Map()
let set = new Set();
let array = [] // 增
map.set('t', 1);
set.add({ t: 1 });
array.push({ t: 1 })
console.info('map-set-array', map, set, array); // 删
map.delete('t');
set.forEach(item => item.t ? set.delete(item) : '');
let index = array.findIndex(item => item.t);
array.splice(index, 1);
console.info('map-set-array-empty', map, set, array); // 改
map.set('t', 2);
set.forEach(item => item.t ? item.t = 2 : '');
array.forEach(item => item.t ? item.t = 2 : '');
console.info('map-set-array-modify', map, set, array); // 查
let map_exist = map.has('t'); // 时间复杂度O(1)
let set_exist = set.has({ t: 1 });
let array_exist = array.find(item => item.t); // O(n)
console.info('map-set-array', map_exist, map_exist, array_exist);

通过对比,map的API更加简单,Array需要遍历才能进行查,改,删的操作,set在进行删,改操作时也需要遍历。因此优先使用map

Map、Set和Object对比

let item = { t: 1 };
let map = new Map();
let set = new Set();
let obj = {}; // 增
map.set('t', 1);
map.set(3, 2);
set.add(item);
obj['t'] = 1;
obj[3] = 2;
console.info('map-set-obj', obj, map, set); // 删
map.delete('t');
set.delete(item);
delete obj['t'];
console.info('map-set-obj-empty', obj, map, set); // 改
map.set('t', 2);
item.t = 2;
obj['t'] = 2;
console.info('map-set-obj-modify', obj, map, set); // 查
console.info({
map_exist: map.has('t'),
set_exist: set.has(item),
obj_exist: 't' in obj
})

通过对比可以发现:

  • 能使用map的优先使用,不使用数组
  • 考虑数据的唯一性,考虑使用set,不使用Object

ES6之新的数据结构的更多相关文章

  1. ES6的新特性(12)——Set 和 Map 数据结构

    Set 和 Map 数据结构 Set 基本用法 ES6 提供了新的数据结构 Set.它类似于数组,但是成员的值都是唯一的,没有重复的值. Set 本身是一个构造函数,用来生成 Set 数据结构. co ...

  2. ES6常用新特性

    https://segmentfault.com/a/1190000011976770?share_user=1030000010776722 该文章为转载文章!仅个人喜好收藏文章! 1.前言 前几天 ...

  3. es6学习笔记8--Map数据结构

    Map Map结构的目的和基本用法 JavaScript的对象(Object),本质上是键值对的集合(Hash结构),但是只能用字符串当作键.这给它的使用带来了很大的限制. var data = {} ...

  4. js ES6 Set和Map数据结构详解

    这篇文章主要介绍了ES6学习笔记之Set和Map数据结构,结合实例形式详细分析了ECMAScript中基本数据结构Set和Map的常用属性与方法的功能.用法及相关注意事项,需要的朋友可以参考下   本 ...

  5. ES6的新特性(11)——Class 的继承

    Class 的继承 简介 Class 可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多. class Point { } class ColorPoint ...

  6. es6 Set 和Map 数据结构

    ES6提供了新的数据结构Set,它类似于数组,但是成员的值都是唯一的,没有重复的值. Set 本身是一个数据结构,用来生成Set 数据结构. const s = new Set(); [2,3,5,4 ...

  7. ES6的新方法实现数组去重

    ES6里新添加了两个很好用的东西,set和Array.from. set是一种新的数据结构,它可以接收一个数组或者是类数组对象,自动去重其中的重复项目. 在这我们可以看见,重复的项目已经被去掉了,包括 ...

  8. 看es6 字符串新方法有感

    'x'.repeat(3) // "xxx" 'hello'.repeat(2) // "hellohello" 'na'.repeat(0) // " ...

  9. 漫谈数组去重复方法(亮点是ES6的新API)

    方法1: 利用遍历的思想来进行. <!DOCTYPE html><html lang="en"><head> <meta charset= ...

随机推荐

  1. 20-02-27 hive表的几个问题

    1.hive表的动态分区 2.hive  表如何修改列名 3.group  by  对统计指标的影响  (group by 的本质) 4.row_number 对数据的影响

  2. 【C语言】(数组)C语言字符串中的小写字母转换为大写字母

    先判断后转化 原理: 这类题目主要通过ASCII(美国信息交换标准代码)码差值实现,A对应ASCII码十进制数字是65,a对应ASCII码十进制数字是97,即大小写字母之间ASCII码差值为32,想要 ...

  3. pillow 初级用法

    # 转载至:https://www.cnblogs.com/apexchu/p/4231041.html Image类 Pillow中最重要的类就是Image,该类存在于同名的模块中.可以通过以下几种 ...

  4. WebApplicationInitializer初始化web应用,不需要web.xml

    web应用的上下文层次结构 很多时候加的切面不起作用,是因为加错地方了 1.直接初始化,上下文只有一个context import org.springframework.web.WebApplica ...

  5. Emprie 使用基础笔记

    0x01 简介 empire 是一个后渗透攻击框架,具有加密通信和灵活框架的功能.Empire可以在不需要Powershell.exe的情况下执行PowerShell代理,后期利用的模块很强大,如sc ...

  6. 洛谷P1908 逆序对(线段树解法)

    题目描述 猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计.最近,TOM老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定 ...

  7. Java面向对象编程 -3.2

    使用this调用本类方法 除了调用属性之外,this也可以实现方法的调用,但是对于方法的调用就必须考虑构造与普通方法 构造方法调用(this()):使用关键字new实例化对象的时候才会调用构造方法: ...

  8. docker运行安装mysql postgres

    安装mysql [root@host1 ~]# docker images -a REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/mysql 5.7 4d ...

  9. 关于calendar修改前的代码和修改后的代码

    Java编写的日历,输入年月,输出这个月的日期与星期 修改前的代码: import java.io.BufferedReader; import java.io.IOException; import ...

  10. 基于通用二进制方式安装MySQL-5.7.24(比源码安装MySQL快许多)及破密码

    确保系统中有依赖的libaio软件 yum -y install libaio 使用wget命令下载mysql-5.7.24软件包 wget http://mirrors.sohu.com/mysql ...