ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。很多时候我们把Set叫做 集合,但是,Set可以是集合,集合不一定是Set。
一、set的基本用法:
1.初始化,声明一个Set
let s1 = new Set([1, 2, "2", 3, 4, 4, 5]);console.log(s1); // 返回集合对象 => Set(6) {1, 2, "2", 3, 4, 5}
1)向Set加入值的时候,不会发生类型转换,所以 2
和 "2"
是两个不同得值,使用的算法叫做"Same-value-zero equality",它类似于运算符( ===
),注意:Set内部,两个NaN相等,会去除重复的NaN;
2) 上面说到key是唯一的,所以在new一个集合实例时,如果有重复的值,会自动去重;
3) new出来的Set集合对象,需要传入一个数组,因此灵活运用扩展运算符和集合,对数组进行操作;
let s2 = [1,3,5,2,3,5,7]let newArr = [...new Set(s2)];console.log("newArr",newArr); // newArr (5) [1, 3, 5, 2, 7]
2.利用Set对JSON数据去重
let arr = [ { id: 1, pid: 1 }, { id: 2, pid: 1 }, { id: 2, pid: 1 }, { id: 3, pid: 1 }, { id: 6, pid: 1 }, { id: 3, pid: 1 }, { id: 6, pid: 1 }, ];let temparr = [...new Set(arr.map((item) => JSON.stringify(item)))];let resultArr = temparr.map((item) => JSON.parse(item));console.log(resultArr);
打印结果:
这样就能拿到去重后的数据了;
二、属性
1.Set.prototype.constructor
Set的构造函数,默认就是Set函数
2.Set.prototype.size
返回Set实例的成员总数。
三、方法
Set的实例方法分为两种:操作方法(用于操作数据) 和遍历方法 ( 用于遍历成员 );
1 操作方法:
add(value):添加某个值,返回Set结构本身;
delete(value):删除某个值,返回一个布尔值,表示是否删除成功;
has(value):返回一个布尔值,表示是否含有该成员;
clear():清楚所有成员,没有返回值;
详细代码如下:
// Set方法 // add(); let s3 = new Set(); s3.add(1).add('2').add(3); s3.add('四'); console.log(s3); // Set(4) {1, "2", 3, "四"} // delete(); s3.delete('2'); console.log(s3); // Set(3) {1, 3, "四"} // has(); console.log(s3.has('2')); // false // clear(); s3.clear(); console.log(s3); // Set(0) {}
2 遍历方法:
keys():返回建名的遍历器;
values():返回建值的遍历器;
entries():返回建值对的遍历器;
forEach():使用回调函数遍历每个成员;
注意:Set
的遍历顺序就是插入顺序。这个特性有时非常有用,比如使用Set
保存一个回调函数列表,调用时就能保证按照添加顺序调用。
如下:
可以直接用 for of遍历Set
// 遍历方法 let s4 = new Set([1, 2, "3"]); // for in 和 for of的区别是:in 是遍历对象,of是遍历值 for (let i of s4) { console.log(i); }; // 1 // 2 // "3"
Set也有forEach()方法
// forEach()方法 let s5 = new Set([1, 2, "3"]); s5.forEach((val,key)=> console.log(key + ':' + val)); // 1:1 // 2:2 // 3:3
注意:Set 结构的键名就是键值(两者是同一个值),因此第一个参数与第二个参数的值永远都是一样的。
四、集合实践
1.并集(Union)
let s6 = new Set(['a','b','c']); let s7 = new Set(['c','a','d']); // 并集 let union = new Set([...s6,...s7]); console.log(union); // Set(4) {"a", "b", "c", "d"};
2.交集(Intersect)
let s6 = new Set(["a", "b", "c"]); let s7 = new Set(["c", "a", "d"]); // 交集 let intersect = new Set([...s6].filter((it) => s7.has(it))); console.log(intersect); // Set(2) {"a", "c"};
3.差集(Difference)
let s6 = new Set(["a", "b", "c"]); let s7 = new Set(["c", "a", "d"]); // 差集 let difference = new Set([...s6].filter((it) => !s7.has(it))); console.log(difference); // Set(1) {"b"};
如果想在遍历操作中,同步改变原来的 Set 结构,目前没有直接的方法,但有两种变通方法。一种是利用原 Set 结构映射出一个新的结构,然后赋值给原来的 Set 结构;另一种是利用Array.from方法。
代码如下(示例):
// 方法一let s8 = new Set([1, 2, 3]);s8 = new Set([...s8].map(val => val * 2));// s8的值是Set(3) {2, 4, 6}// 方法二let set = new Set([1, 2, 3]);set = new Set(Array.from(set, val => val * 2)); // set的值是2, 4, 6