ES6 内 的数据结构Set
特性:类似数组,但是它的最大特性就是所有元素都是唯一的,没有重复的值。
Set本身是一个构造函数,用来生成Set数据结构。
const s = new Set();
[2,3,3,5,6,7,7,4,3].forEach( x => s.add(x));
for(let i of s){
console.log(i);
}
//2 3 5 6 7 4
可以看到通过add()向Set结构内添加数据,返回的Set结构内无重复数据。
Set函数可以接受一个数组作为参数,用来初始化。
const set = new Set([1,2,3,4,4]);
set ; // [ Set { 1, 2, 3, 4 } ]
[...set]; //[ 1, 2, 3, 4 ] 解构获取Set内部的值
set.size; // 4 set的长度获取
数组去重也可这样做:
// 去除数组的重复成员
[...new Set(array)]
除了单数组去重以外,也可进行多数组合并去重:
let arr1 = [1, 2, 3, 4]
let arr2 = [2, 3, 4, 5, 6]
let setc = new Set([...arr1, ...arr2])
console.log("set",setc)
//setc: Set { 1, 2, 3, 4, 5, 6 }
上述单数组去重的方法,也可用于字符串去重:
[...new Set('ababbc')].join('')
// "abc"
向Set添加数据的三种情况:
//情况1
let set = new Set();
set.add("5");
set.add(5);
set //Set { '5', 5 }
//情况2
let set1 = new Set();
let a = NaN;
let b = NaN;
set1.add(a);
set1.add(b);
set1 //Set { NaN }
//情况3
let set2 = new Set();
set2.add({});
set2.size //1
set2.add({})
set2.size //2
set2 //Set { {}, {} }
上述代码表示:向 Set 加入值的时候,不会发生类型转换,所以5
和"5"
是两个不同的值。
Set 内部判断两个值是否不同,使用的算法叫做“Same-value-zero equality”,它类似于精确相等运算符(===
),主要的区别是向 Set 加入值时认为NaN
等于自身,而精确相等运算符认为NaN
不等于自身。
由于两个空对象不相等,所以它们被视为两个值。
Set的实例属性和方法
Set结构的实例有以下属性:
- constructor: 构造函数,默认是Set函数
- size: 返回Set实例的成员总数
Set实例的方法分为两大类:操作方法(用于操作数据)和遍历方法(用于遍历成员)。
1.add(value): 添加某个值,返回Set结构本身。
let set = new Set();
set.add("5");
set.add(5);
set //Set { '5', 5 }
2.delete(value): 删除某个值,返回布尔值,表示删除是否成功。
3.has(value): 返回一个布尔值,表示该值是否为Set成员。
let set = new Set();
set.add("5");
set.add(5);
set // Set { '5', 5 }
set.delete('5'); //删除5
set // Set { 5 }
// 判断Set是否有该元素
set.has(5); // true 是set的成员
set.has('5'); // false 不是set的成员,已经被删掉了
4.clear(): 清除所有成员,没有返回值。
let set = new Set();
set.add("5");
set.add(5);
set // Set { '5', 5 }
set.clear() // Set {}
Object结构与Set结构的对比:
// 对象的写法
const properties = {
'width': 1,
'height': 1
};
if (properties[someName]) {
// do something
}
// Set的写法
const properties = new Set();
properties.add('width');
properties.add('height');
if (properties.has(someName)) {
// do something
}
数组转Set结构
const items = new Set([1, 2, 3, 4, 5]);
const array = Array.from(items);
这也提供了数组去重的另一种方法:
function dedupe(array) {
return Array.from(new Set(array));
}
dedupe([1, 1, 2, 3]) // [1, 2, 3]
遍历操作
Set结构的实例有四个遍历方法,可以用于遍历成员。
- keys(): 返回键名的遍历器
- values(): 返回键值的遍历器
- entries(): 返回键值对的遍历器
- forEach(): 使用回调函数遍历每个成员
需要特别指出的是,Set
的遍历顺序就是插入顺序。这个特性有时非常有用,比如使用 Set 保存一个回调函数列表,调用时就能保证按照添加顺序调用。
由于Set的键名和键值是同一个值,它的每一个元素的key和value是相同的,所有keys()和values()的返回值是相同的,entries()返回的元素中的key和value是相同的。
let set = new Set(['1', '2', '3']);
for (let item of set.keys()) {
console.log(item);
}
// 1
// 2
// 3
for (let item of set.values()) {
console.log(item);
}
// 1
// 2
// 3
for (let item of set.entries()) {
console.log(item);
}
//[ '1', '1' ]
//[ '2', '2' ]
//[ '3', '3' ]
Set 结构的实例默认可遍历,它的默认遍历器生成函数就是它的values
方法。
Set.prototype[Symbol.iterator] === Set.prototype.values
// true
forEach:
let set = new Set([1, 4, 9]);
set.forEach((value, key) => console.log(key + ' : ' + value))
// 1 : 1
// 4 : 4
// 9 : 9
扩展运算符和Set结构相结合,就可以去除数组的重复成员。
let arr = [1,2,3,3,4,5];
let unique = [...new Set(arr)];
// [1,2,3,4,5]
数组的map和filter也可用于Set结构。
let set = new Set([1,2,3]);
set = new Set([...set].map(x => x*2));
// Set { 2, 4, 6 }
let set = new Set([1,2,3,4,5]);
set = new Set([...set].filter(x => x % 2 == 0));
console.log(set);
// Set { 2, 4 }
使用Set结构很容易实现并集(Union)、交集(Intersect)和差集(Difference)。
let a = new Set([1,2,3]);
let b = new Set([3,4,5]);
// 并集
let union = new Set([...a, ...b]);
union // Set { 1, 2, 3, 4, 5 }
//交集
let intersect = new Set([...a].filter(x =>b.has(x)));
intersect //Set { 3 }
//差集
let difference = new Set([...a].filter(x => !b.has(x)));
difference // Set { 1, 2 }
详细请查看ES6 Set教程