Set和Map数据结构


本系列属于阮一峰老师所著的ECMAScript 6 入门学习笔记


Set

Set类似数组,但是成员的值都是唯一的没有重复的值,Set本身是一个构造函数,用来生成Set数据结构

const s = new Set()
[2,3,4,5,2,3,2].forEach(x => s.add(x))
for(let i of s){
  console.log(i)
}
// 2,3,4,5

const set = new Set([1,2,3,4,4])
[...set] // [1,2,3,4]
set.size // 4

//向Set中加入值的时候,不会发生类型转换,5与'5'是两个值,判断值是否相等类似===,区别是NaN等于自身
const set = new Set([NaN,NaN]) // Set(1) {NaN}

//两个对象总是不相等的
const set = new Set([{},{}]) // Set(2) {{...},{...}}
Set实例的属性和方法

有以下属性:

  • Set.prototype.constructor :构造函数,默认是Set函数
  • Set.prototype.size :返回Set实例的成员总数

有以下方法:

  • add(value) :添加某个值,返回Set结构本身
  • delete(value) :删除某个值,返回布尔值,表示删除是否成功
  • has(value) :返回一个布尔值,表示该值是否为Set的成员
  • clear() :清除所有成员,无返回值
s.add(1).add(2).add(2)
s.size // 2
s.has(1) // true
s.has(3) // false
s.delete(2) // true

// Array.from方法可以将Set结构转为数组
const items = new Set([1,2,3,4,5])
const array = Array.from(items) // [1,2,3,4,5]

// 利用Set去重
function dedupe(array){
    return Array.from(new Set(array))
}
Set的遍历操作

有以下四种遍历方法,遍历顺序就是插入顺序:

  • keys() :返回键名
  • values() :返回键值
  • entries() :返回键值对
  • forEach() :使用回调函数遍历每个成员
let set = new Set(['red','green','blue'])

// Set结构默认的遍历器生成函数就是values,所以遍历value时可以直接省略values方法直接遍历
Set.prototype[Symbol.iterator] === Set.prototype.values // tue

for(let x of set){
    console.log(x)
}
// red green blue

set.forEach((value,key) => console.log(key + ':' + value))
// red:red green:green blue:blue

let arr = [...set] // ['red','green','blue']
// 与拓展运算符结合去重
let unique = [..new Set(set)] // ['red','green','blue']
// 结合数组方法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)) // Set {2,4}

//利用Set可以很方便的实现并集、交集、差集
let a = new Set([1,2,3])
let b = new Set([4,3,2])
let union = new Set([...a,...b]) // Set {1,2,3,4}
let intersect = new Set([...a].filter(x => b.has(x))) // Set {2,3}
let difference = new Set([...a].filter(x => !b.has(x))) // Set {1}

// 改变原有Set结构的方法
let set = new Set([1,2,3])
set = new Set([...set].map(val => val*2)) // set {2,4,6}
set = new Set(Array.from(set,val => val*2)) // set {2,4,6}
WeakSet

WeakSetSet类似,区别在于:WeakSet的成员只能是对象;WeakSet对象都是弱引用,即垃圾回收机制不考虑WeakSet对该对象的引用,也就是说如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于WeakSet

因此,WeakSet的成员不适合引用,因为它随时会消失,也不可以遍历

const a = [[1,2],[3,4]]
const ws = new WeakSet(a) // WeakSet {[1,2],[3,4]}
// WeakSet只有add()、delete()、has()三种方法,无size属性,不可遍历,无clear()方法
Map

传统对象键值只能是字符串,Map提供了一种方法,可以接收键值不仅为字符串,提供"值-值"对应的结构

// 利用Map结构的set方法,将对象作为键
const m = new Map()
const o = {p:'Hello World'}
m.set(o,'content')
m.get(o) // 'content'
m.has(o) // true
m.delete(o) // true

// Map结构接收数组参数
const map = new Map([['name','张三'],['title','Angus']])
map.size // 2
map.has('name') // true
map.get('name') // 张三

// 不仅是数组,所有具有Iterator接口、每个成员都是一个双元素的数组数据结构都可以作为Map函数的参数
const set = new Set([['foo',1],['bar',2]])
const m1 = new Map(set)
m1.get('foo') // 1

// 对一个键多次赋值,后面的值将会覆盖前面的值
const map = new Map()
map.set(1,'1').set(1,'2')
map.get(1) // '2'
Map实例的属性和操作方法
const map = new Map()
map.set('foo',true).set('bar',false)
map.size // 2
map.get('foo') // true
map.has('foo') // true
map.delete('foo') // true
map.clear()
Map实例的遍历方法
const map = new Map([['F','no'],['T','yes']])
// keys()方法
for(let key of map.keys()){
    console.log(key) // 'F' 'T'
}
// values()方法
for(let value of map.values()){
    console.log(value) // 'no' 'yes'
}
// entries()方法
for(let item of map.entries()){
    console.log(item) // ['F','no'] ['T','yes']
}
// Map结构默认的遍历器接口就是entries()方法
[...map] // [['F','no'],['T','yes']]
// 结合数组的map和filter方法,实现Map的遍历和过滤
const map = new Map().set(1,'a').set(2,'b')
const map1 = new Map([...map].filter(([k,v]) => k<3)) // Map(2) {1=>'a',2=>'b'}
const map2 = new Map([...map].map(([k,v]) => [k*2,'_'+v])) // Map(2) {2=>'_a',4=>'_b'}
// forEach方法
map.forEach(function(value, key, map) {
  console.log("Key: %s, Value: %s", key, value); // Key:1,Value:a Key:2,Value:b
});
// forEach接收第二个参数用来绑定this
const reporter = {
  report: function(key,value){
    console.log('Key:%s,Value:%s',key,value)
  }
}
map.forEach(function(value,key,map){
    this.report(key,value) // Key:1,Value:a Key:2,Value:b
},reporter)
WeakMap

WeakMapMap类似,但有两点区别:WeakMap只接收对象作为键名;WeakMap键名所指向的对象,不计入垃圾回收机制,这一点与WeakSet相同。

WeakMap不能使用size属性,不能遍历,也不支持clear

可用方法有get()set()has()delete

优质内容筛选与推荐>>
1、SpringBoot快速入门
2、mybatis映射文件配置-1对多
3、python每日一题:股市里爬虫获得近十年A股上升或下跌的天数
4、python-os模块
5、Django框架 之 Ajax


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号