Set和Map数据结构

1,153 阅读4分钟

#Set 定义:ES6定义的一种新的数据结构。Set是一个构造函数,用于生成set实例。 特点: 类似于数组,成员唯一

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

Set实例的属性和方法

1.属性

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

2.方法

  • add(values):添加某个值,返回Set结构本身 向Set加入值不会发生类型转换,值比较类似于“===”,但是区别是认为NaN与自身相等

    let set = new Set();
    let a  = NaN;
    let b  =NaN;
    set.add(a).add(b);//返回set本身则可以链式调用
    set;//Set {NaN}
    
  • delete(values):删除某个值,返回布尔值表示是否删除成功

  • has(values):是否为Set的成员,返回布尔值

  • clear():清空所有成员,没有返回值

3.遍历操作

  • keys():返回键名的遍历器
  • values():返回值的遍历器(默认的遍历器生成函数Set.prototype[Symbol.iterator] === Set.prototype.values //true
  • entries():返回键值对的遍历器
  • forEach():使用回调函数遍历每个成员
let set = new Set([1,2,3]);
set.forEach((value,index) => console.log(value*2)) //2 //4 //6

Set结构和数组的转换

1.Set转数组


const set = new Set([1,2,3]);
let arr = [];

//使用Array.from
arr = Array.from(set);
arr; //[1, 2, 3]

//for of
for(let item of set){
	arr.push(item)
}
arr; //[1, 2, 3]

2.数组转Set

let arr = [1,2,3];
const set = new Set(arr);
set;//Set(3) {1, 2, 3}

Set的简单应用

1.数组去重

let arr =[2,3,4,5,5,4];
let newArr = [...new Set(arr)]
newArr;//(4) [2, 3, 4, 5]

2.并集、交集、差集

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

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

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

//差集
let difference = new Set([..a].filter(x => !b.has(x)));
//Set(1) {1}

#Map 定义:ES6定义的一种新的数据结构。Map是一个构造函数,用于生成map实例。 特点:类似于对象,是键值对集合,键范围不限于字符串(各种类型包括对象)。

const m = new Map();
const  o = {P:"Hello World"};
m.set(o,"content");
m.get(o); //"content"

注意任何具有Iterator(遍历器)接口且每个成员都有一个双元素数组的数据结构都可以当做Map构造函数的参数。

原生具备Iterator结构的数据结构如下:(相关阅读Iterator

  • Array
  • Map
  • Set
  • String
  • TypedArry
  • 函数里的arguments对象
  • NodeLIst 对象
//使用set来创建map
const set = new Set([
	['foo',1],
	['bar',2]
])
const m1 = new Map(set);
m1.get('foo'); //1

//使用数组创建map
const m2 = new Map([['bar',3]])//这里如果使用new Map(['bar',3])则会报错,因为数组中第一个元素不为双元素(Iterator value bar is not an entry object)
m2; //Map(1) {"bar" => 3}

//使用map创建map
const m3 = new Map(m2);
m3.get('bar');//3

Map的键实际是和内存绑定的,只要内存不一样,就是为两个键。 如果键是一个简单类型的值,严格相等则是为一个键(NaN除外,是为一个键)

const map = new Map();
map.set(['a'],5);
map.get(['a']); //undefined,数组是引用类型,定义set的['a']和get的['a']不是同一个数组对象

//继续
let a = ['b'];
let b = a;
map.set(a,6);
map.get(b);//6,a和b为引用了同一个数组对象

##Map实例的属性和操作方法 1.属性

  • size:返回Map成员总数;
  • set(key,value):设置key所对应的键值,返回整个Map结构。如果key已有则更新,没有则创建。
  • get(key):读取key对应的键值,找不到key则返回undefined。
  • has(key):某个键是否在Map结构中,返回布尔值。
  • delete(key):删除某个键,返回布尔值。
  • clear():清除所有成员,没有返回值

2.遍历方法

  • keys():返回键名的遍历器
  • values():返回值的遍历器
  • entries():返回键值对的遍历器(默认的遍历器接口) map[Symbol.iterator] === map.entries //true
  • forEach():使用回调函数遍历每个成员 Map的遍历顺序就是插入顺序
const map = new Map([
	['name','Lucas'],
	['age','18']
]);

for(let key of map.keys()){
	console.log(key)
}
//age name


for(let value of map.values()){
	console.log(value )
}
// Lucas 18

for(let item of map.entries()){
	console.log(item )
}
//(2) ["name", "Lucas"]
//(2) ["age", "18"]

##Map与其他数据结构的转换 1.Map与数组

//map转数组
const myMap = new Map().set(true,7).set({foo:3},['abc']);
[...myMap]
//[[true,7],[{foo:3},['abc']]]

//数组转map
new Map([
	[true,7],
	[{foo:3},['abc']]
])
//0:{true => 7}
  1:{Object => Array(1)}

2.Map与对象 如果Map的所有键都是字符串,则可以转为对象。

//map转对象
const myMap = new Map().set('name','zoom').set('age',8);
let obj = Object.create(null);
for(let [key,val] of myMap){
	obj[key] = val;
}
obj; //{name: "zoom", age: 8}

//对象转map
const myMap2 = new Map();
let obj = {name: "zoom", age: 8};
for(let k of Object.keys(obj)){
	myMap2.set(k,obj[k]);
}
myMap2; //Map(2) {"name" => "zoom", "age" => 8}

3.Map与JSON 这一部分笔者没有研究透彻,详情可参考:Map