Set和Map数据结构

1,423 阅读5分钟

一、Set

1、概述:

  • ES6提供新的数据结构Set,类似于数组,但是成员的值是唯一的,没有重复值。也就是说Set是不重复的值的集合

  • 没有键名,只有键值,或说键名和键值是同一个值,两个值永远是相等的

  • 接受一个数组作为参数,用来初始化

const set = new Set([1,2,3,4,4]);
consle.log(set);//[1,2,3,4]
console.log([...set]);//[1,2,3,4]

2、属性和方法

操作方法:

  • .add( ) 添加某一个值,返回的是Set结构本身

  • .delete( ) 删除某个值,返回一个布尔值,表示删除是否成功

  • .has( ) 返回一个布尔值,表示该值是否为Set的成员

  • .clear( ) 清除所有成员,没有返回值

遍历方法:

  • .keys( ) 返回键名
  • .values( ) 返回键值

​ 因为Set没有键名只有键值,或说键名和键值是同一个值,所以.values( )和.keys()行为一致

​ Set结构的实例默认可遍历,所以可以省略.values方法;

let set = new Set(["red", "green", "blue"]);
for (let i of set.keys()) {
  console.log("set.keys:", i);
}

let set2 = new Set(["red", "green", "blue"]);
for (let i of set2.values()) {
  console.log("set.values:", i);
}

let set4 = new Set(["red", "green", "blue"]);
for (let i of set4) {
   console.log("Set结构的实例默认可遍历:", i);
}
  • .entries( ) 返回键值对
  • .forEach( )

3、Set结构如何转为数组:使用Array.from

Array.from方法可以将 Set 结构转为数组

4、使用场景:

(1)去除数组重复成员

//实例1
const set = new Set([1, 2, 3, 4, 4]);
console.log(set);//[1,2,3,4]

//实例2
const items = new Set([1, 2, 3, 4, 4, 5, 6, 6]);
const array = Array.from(items);//[1,2,3,4,5,6]

//实例3
function unique(array){
   //判断是不是数组,不是就直接return
  if (!(arr instanceof Array)) {
    console.log("传入的不是数组");
    return
  } else {
     return Array.from(new Set(array));//Array.from方法可以将Set结构转为数组
  }
}

unique([1,1,2,3]);//[1,2,3]
unique('111');//传入的不是数组

注意:Set该方法只针对一般数组,比如[1, 2, 3, 4, 4]这种,如果数组里面还有对象,该方法不适用,比如 [{a: 1} , {a: 1} , {a: 2}]这种。

(2)去除字符串重复字符

const str = "ascddsdfg";
const DEPLICATE_STR = new Set(str);
console.log([...DEPLICATE_STR].join(''));//ascdfg

join( )将数组中的所有元素转换成一个字符串;

(3)求并集/交集/差集

数组的map和filter方法可以间接用于Set,Set本身没有map和filter方法的哦~

let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);

let union = [...new Set([...a, ...b])];
console.log("并集=", union); //[1,2,3,4]

let intersect = [...new Set([...a].filter((x) => b.has(x)))];
console.log("交集=", intersect); //[2,3]

let difference = Array.from(new Set([...a].filter((x) => !b.has(x))));
console.log("差集=", difference); //[1]

5、WeakSet和Set的区别:

WeakSet和Set的区别:

  • 都是不可重复值的集合

  • 成员只能是对象

  • 没有size属性,不可遍历

用处:

WeakSet的一个用处,是储存DOM节点,而不担心这些节点从文档移除时,会引发内存泄漏;

二、Map

1、概述

  • 本质上是健值对的集合,类似集合;

  • 传统键值对都是“字符串-值”的对应,有所限制,所以Map结构提供了“值-值”的对应;

  • 可以遍历,可以跟各种数据格式转换

  • 接受一个数组作为参数,数组成员是一个个表示键值对的数组;

  • Set和Map都可以生成新的Map;

  • 只有对同一个对象的引用,Map 结构才将其视为同一个键;

​ Map 的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键。

const map = new Map();
map.set(['aaa',5]);
console.log(map.get(['aaa']));//undefined

//只有对同一个对象的引用,Map 结构才将其视为同一个键;所以必须要指向同一个对象,将其存为一个对象;
const map = new Map();
const k1 = ['aaa'];
map.set(k1,5);
console.log(map.get(k1));//5

2、属性和方法

操作方法:

  • .set( )

  • .get( )

  • .delete( )

  • .has( )

  • .clear( )

遍历方法:

  • .keys( ) 返回键名的遍历器

  • .values( ) 返回键值的遍历器

  • .entries( ) 返回所有成员的遍历器

  • forEach( ) 遍历Map的所有成员

Map的遍历顺序就是插入的顺序

3、与其他数据结构的互相转换

(1)Map转数组: 使用扩展运算符

(2)数组转Map

(3)Map转对象:Object.create( )

(4)对象转Map:Object.entries( )

(5)Map转JSON

(6)JSON转Map

//1、Map转数组
const map0 = new Map().set(1,'a').set(2,'b');
console.log(":",[...map0]);//[{1,'a'},{2,b}]
console.log("Map转数组:",[...map0].keys());//[1,2]
console.log("Map转数组:",[...map0].values());//['a','b']

//2、数组转Map,将数组直接传入Map构造函数
new Map([
[true,7],
[{foo:3},['abc]]
])
 
//3、Map转对象
 const map1 = new Map().set(1,'a').set(2,'b');
 function strMapToObj(strMap){
   let obj = Object.create(null);//创建一个空对象,这样创建的对象干净,除了自身属性之外没有其他属性和方法
   for(let [k,v] of strMap){
     obj[k] = v;
   }
   return obj
 }
 strMapToObj(map1);

//4、对象转数组
const obj1 = {1:'a',2:'b'}
let map2 = new Map(Object.entries(obj))//Object.entries()返回一个给定对象自身可枚举属性的键值对数组[['1','a'],['2','b']]
 

4、使用场景:

可以使用数组的map和filter方法,Map本身是没有map和filter方法的

(1)实现Map的过滤和遍历

const map0 = new Map().set(1,'a).set(2,'b).set(3,'c');

const map1 = new Map([...map0].filter(([k,v])=>k < 3));
const map2 = new Map([...map0].map(([k,v])=>[k*2,'_'+v])) 

5、WeakMap和Map的区别

  • 只接受对象作为键名(null除外);
  • WeakMap的键名所指的对象,是弱引用,即不会被计入垃圾回收机制;

​ (也就是说一旦不需要了,WeakMap里面的键名对象和所对应的键值对就会自动消失,不用手动删除)

​ (注意:弱引用的只是键名,而不是键值,键值依然是正常引用)

  • WeakMap的专用场合:

  • 它的键所对应的对象,可能会在未来消失。

  • WeakMap结构有助于防止内存泄漏。

在API上的区别:

  • 没有遍历操作,即没有keys()、values()、entries()方法,也没有size属性;

  • 无法清空,即不支持clear()方法,因此WeakMap只有set( )、get( )、has( )、delete( )方法;

学习资料:

ECMAScript 6 入门-Set 和 Map 数据结构