Set数据结构
Set
是ES6
提供的一种新的数据结构,类似于数组,但是成员值都是唯一的,没有重复值;
Set
本身就是一个构造函数,用来生成Set
数据结构
// 示例一 通过add方法添加元素
var s = new Set();
[2, 3, 5, 4, 5, 2, 2].map(x => s.add(x));
for (let i of s) {
console.log(i); // 2, 3, 5, 4
}
// 示例二 参数形式初始化元素
var s = new Set([1, 2, 2, 3, 4, 5, 5, 6])
console.log([...s]) // 1, 2, 3, 4, 5, 6
Set实例的属性和方法
属性
Set.prototype.constructor
构造函数,默认就是构造函数Set.size
返回Set
示例的成员总数
var set = new Set([1, 2, 3, 4])
console.log(Set.prototype.constructor === Set) // true
console.log(set.size) // 4
方法
add(value)
添加某个值,返回Set数据结构本身
var set = new Set()
set.add(1)
set.add(2)
set.add(1)
for(let i of set) {
console.log(i) // 1, 2
}
delete(value)
删除某个值,返回一个布尔值,表示删除是否成功
var set = new Set([1, 2, 3, 5])
console.log(set.delete(1)) // true
console.log(set.delete(4)) // false
has(value)
返回一个布尔值,表示该值是否为Set
的成员
// Object结构
var user = {
name: 'xx'
age: 12
}
// 判断是否存在某个属性
// if (user['name']) {
// // do something
// }
// Set结构
var set = new Set([1, 2, 3, 5])
console.log(set.has(1)) // true
console.log(set.has(4)) // false
clear()
清除所有成员,没有返回值
var set = new Set([1, 2, 3, 4])
console.log(set.size) // 4
set.clear()
console.log(set.size) // 0
Set结构的遍历操作
由于
Set
结构没有键名,只有键值(或者说键名和键值是同一个值)
Set
结构的实例默认可遍历,它的默认遍历器生成函数就是它的values
方法
keys() values() entries()
keys()
返回键名的遍历器values()
返回键值的遍历器entries()
返回键值对的遍历器
var set = new Set(['red', 'green', 'blue'])
console.log(Set.prototype[Symbol.iterator] === Set.prototype.values) // true
// keys
for (let item of set.keys()) {
console.log(item) // red green blue
}
// values
for (let item of set.values()) {
console.log(item) // red green blue
}
// entries
for (let item of set.entries()) {
console.log(item)
// ['red', 'red']
// ['green', 'green']
// ['blue', 'blue']
}
// 直接遍历set示例
for (let x of set) {
console.log(x); // red green blue
}
forEach()
- 使用回调函数遍历每个成员,用于对每个成员执行某种操作,没有返回值
var set = new Set([1, 2, 3, 4, 5])
set.forEach(s => {
console.log(s * 2) // 2, 4, 6, 8, 10
})
遍历的应用
数组去重
- 采用同值相等的比较方法
NaN === NaN
- 引用类型的数据永远不相等
{} !== {}
// 方式一 set + ...拓展运算符
var set = new Set([1, 2, 3, 3, 4, 5, 6, 6])
var unique = [...set];
cnosole.log(unique) // [1, 2, 3, 4, 5, 6]
// 方式二 set + Array.from函数
var set = new Set([1, 2, 3, 3, 4, 5, 6, 6])
var unique = Array.from(set)
console.log(unique) // [1, 2, 3, 4, 5, 6]
// 同值相等
var set = new Set([1, 2, 3, NaN, NaN, {}, {}])
var unique = [...set]
console.log(unique) // [1, 2, 3, NaN, {}, {}]
使用
map
和filter
等数组方法
// 使用map方法
var set = new Set([1, 2, 3])
set = new Set([...set].map(s => s * 2))
for (let s of set) {
console.log(s) // 2, 4, 6
}
// 使用filter方法
var set = new Set([1, 2, 3])
set = new Set([...set].filter(s => s > 1))
for (let s of set) {
consle.log(s) // 2, 3
}
实现数据之间的并集、交集和差集
var set1 = new Set([1, 2, 3])
var set2 = new Set([1, 3, 5, 7])
// 并集
var union = new Set([...set1, ...set2])
for (var item of union) {
console.log(item) // 1, 2, 3, 5, 7
}
// 交集
var intersect = new Set([...set1].filter(item => set2.has(item)))
for (var item of intersect) {
console.log(item) // 1, 3
}
// 差集
var difference = new Set([...set1].filter(item => !set2.has(item)))
for (var item of difference) {
console.log(item) // 2
}
遍历修改数据源
利用
...
拓展运算符和map
方法
var set = new Set([1, 2, 3])
set = new Set([...set].map(s => s * 2))
for(let s of set) {
console.log(s)
}
利用Array.from的第二个参数,进行数据处理
var set = new Set([1, 2, 3])
set = new Set(Array.from(set, val => val * 2))
for(let s of set) {
console.log(s)
}
Map数据结构
ES6
提供了Map
数据结构,类似于对象,也是键值对的集合,但是键的范围不限于字符串,各种类型的值都可以当做键,解决了传统对象Object
只能使用字符串作为键名的缺陷
// 创建对象的时候进行初始化操作
var map = new Map([['name', 'xxx'], ['age', 22]])
console.log(map.get('name')) // 'xxx'
console.log(map.get('age')) // 22
// 使用set方法添加数据
var map = new Map()
map.set('name', 'xxx')
map.set('age', 22)
console.log(map.get('name')) // 'xxx'
console.log(map.get('age')) // 22
Map结构赋值的一些注意点
- 判断属性名是否存在,使用和
Set
数据结构一样的同值相等判断法
var k1 = ['a']
var k2 = ['a']
var map = new Map([
[true, '123'],
['true', '123'],
[k1, 'foo'],
[k2, 'bar'],
])
console.log(map.get(true)) // 123
console.log(map.get('true')) // 123
console.log(map.get(k1)) // 'foo'
console.log(map.get(k2)) // 'bar'
- 对同一个键值进行对此赋值,后面的值将覆盖前面的值
var map = new Map([
[true, '123'],
['true', '123']
])
console.log(map.get(true)) // 123
map.set(true, '456')
console.log(map.get(true)) // 456
- 获取一个未知的键名,会返回
undefined
var map = new Map([
[true, '123'],
['true', '123']
])
console.log(map.get(false)) // undefined
Map的实例属性和操作方法
size
属性,用来获取map
实例的长度set(key, value)
方法,设置key
对应的键值,如果键名存在,就更新键值;如果键名不存在,就新生成改键get(key)
方法,返回键名对应的键值,没有返回undefined
has(key)
方法,返回一个boolean
值,表示map
对象中是否包含某个键名delete(key)
方法,返回一个boolean
值,删除成功,返回true
;删除失败,返回false
clear()
方法,清空map
对象
var map = new Map([
['name', 'xxx'],
['age', 12]
])
console.log(map.size) // 2
map.set('sex', 'male')
console.log(map.get('sex')) // male
map.set('age', 24)
console.log(map.get('age')) // 24
console.log(map.has('name')) // true
console.log(map.has('weight')) // false
console.log(map.delete('name')) // true
console.log(map.get(name)) // undefined
map.clear()
console.log(map.size) // 0
Map结构的遍历操作
Map
数据结构的遍历操作基本与Set
一致,但是Set[Symbol.iterator] === Set.prototype.entries
Map结构与其他数据结构的转换
Map
与数组之间的相互转换(数组必须是二维数组)
// map => arr
var map = new Map([
['name', 'xxx'],
[age, 24],
])
console.log([...map]) // [['name', 'xxx'], ['age', 24]]
// arr => map
var arr = [[true, 7], [{foo: 3}, ['abc']]]
var map = new Map(arr)
for(let m of map) {
console.log(m) // [true, 7] [{foo: 3}, ['abc']]
}
Map
与对象之间的相互转换
// map => obj
// Map的键都是字符串,它可以转为对象
function strMapToObj(strMap) {
let obj = Object.create(null);
for (let [k,v] of strMap) {
obj[k] = v;
}
return obj;
}
let myMap = new Map().set('yes', true).set('no', false);
strMapToObj(myMap) // { yes: true, no: false }
// obj => map
function objToStrMap(obj) {
let strMap = new Map();
for (let k of Object.keys(obj)) {
strMap.set(k, obj[k]);
}
return strMap;
}
objToStrMap({yes: true, no: false}) // [ [ 'yes', true ], [ 'no', false ] ]
Set和Map的区别
- 都是用来存储数据用的,但是存储的数据格式不同
Set
直接存储任意类型数据,Map
存储数据的时候,必须以key:value
的形式Set
使用forEach
遍历的时候,key
和value
值是一样的; 而map
遍历的时候,key
就是存进去的对象的key
,value
就是存在的值for...of
进行遍历的时候,Set
的[Symbol.iterator]
方法是原型链上的values
方法,而Map
的[Symbol.iterator]
方法是原型链上的entries
方法