Set和Map数据结构

1.set

基本用法:
set是ES6提供的一种新的数据结构,有点像数组,但是他的成员都是唯一的,没有重复的值。其次,set本身就是一个构造函数,是用来生成set数据结构的。
如下:

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

以上代码的意思是通过add方法像Set解构加入成员,最终结果表明Set解构不会添加重复的值。
Set函数可以接受一个数组来作为他的参数,以便用于初始化。

var s= new Set([2,3,3,4,5,3,6]);
[...set]
//2,3,4,5,6

var item = new Set([1,2,2,3,3,4,5]);
var n = item.size;
console.log(n);//5

向Set中加入值时,是不会发生类型转换的,所以3和“3”是不同的两个值,也就是说set内部判断两个值是否相同其实是类似于(===)的,这便意味着,两个对象总是不相等的。
注意:这里有个例外,就是NaN,他在精确相等运算符下是不等于自己的:

var set= new Set();
set.add({});
console.log(set.size); //1
set.add({});
console.log(set.size); //2

上面的代码表示,由于两个空对象并不是精确相等的,所以他们被认为是两个值。

操作方法:

  • add(value):向set中添加值,返回set结构本身。
  • delete(value):删除set中的某个值,返回一个布尔值,表示是否删除成功。
  • has(value):返回一个布尔值,表示该参数是否是set的成员。
  • clear():清除所有成员,没有返回值。

    下面实际操作一下这些方法:

var set= new Set();
set.add(4).add(2).add(4);
for(let i of set){
    console.log(i);//4,2
}
console.log(set.has(2)); //true
console.log(set.has(3)); //false

set.delete(2); //删除此成员
console.log(set.has(2)); //false,表示该成员已经不在set中。

**注意:**Array.from方法可以将set结构转换为数组形式:var item = new Set([1,2,3,4,5]); var array = Array.from(item);,这就提供了一种数组去重的方法:

var arr = [1,2,3,3,2,4,5];
function de(array){
    return Array.from(new Set(array));
}
console.log(de(arr)); //1,2,3,4,5

遍历方法:
Set有4个遍历方法,用于遍历其成员:

  • keys():返回一个键名的遍历器
  • values():返回一个键值的遍历器
  • entries():返回一个键值对的遍历器
  • forEach():使用回调函数遍历每个成员

下面实际操作这些方法:

var set = new Set(['lion','mouse','pig','dog']);
for(let i of set.keys()){
    console.log(i);
}
//lion
//mouse
//pig
//dog

for(let i of set.values()){
    console.log(i);
}
//lion
//mouse
//pig
//dog

for(let i of set.entries()){
    console.log(i);
}
//["lion", "lion"]
//["mouse", "mouse"]
//["pig", "pig"]
//["dog", "dog"]

由于set的成员只有键值,所以他的键名和键值是同一个值,所以keys和values的行为是完全相同的,而entries方法返回的遍历器同时包括键名和键值,所以每次输出一个数组,其中的两个成员都是一样的。
最后,由于扩展运算符(…)内部使用for…of循环,所以其也可以用于set结构。

var set = new Set([1,2,3]);
let arr = [...set];
console,log([...set]);//1,2,3

这就提供了另一个更加方便的数组去重的方法:

let arr = [3,3,2,4,5,4,5,6,7,7];
let unique = [...new Set(arr)];
console.log(unique);    //3,2,4,5,6,7

如此Set在实现交集,并集,差集时就显得格外的方便:

let a = new Set ([1,2,5,8]);
let b = new Set ([2,4,5,9]);
//并集
let union = new Set([...a,...b]);
console.log(union);
//交集
let intersect = new Set([...a].filter(x => b.has(x)));
console.log(intersect);
//差集
let different = new Set([...a].filter(x => !b.has(x)));
console.log(different);

最后: set结构的实例的foEach方法的参数就是一个处理函数,该函数的参数依次为键值,键名,集合本身。另外,forEach方法还可以有第二个参数,表示绑定的对象。
如果想在遍历操作中同步改变原来的set结构,目前没有直接的办法,只有两个可以变通的方法:
a.利用原来的set结构映射出一个新的结构,然后赋值给原来的set结构
b.利用Array.from方法实现
如下:

//方法一
let set = new Set([1,2,3,4,5]);
set = new Set([...set].map(val => val*2));
console.log(set);  //2,4,6,8,10

//方法二
let set = new Set([1,2,3,4,5]);
set = new Set(Array.from(set,val=>val*2));
console.log(set);  //2,4,6,8,10

如此便改变了原来set的结构

2.Map

Map数据结构类似于Hash结构,都是键值对的集合,但是他的键的范围不限于字符串,各种类型的值都可当做键,Map结构提供了“值——值”的对应,是一种更为完善的Hash结构实现。如果你需要“键值对”的数据结构,那么Map肯定比object更合适。

var m = new Map();
var o = {p:"hello world"};
m.set(o,"lion");
console.log(m.get(o)); //lion
console.log(m.has(o)); //true
m.delete(o);
console.log(m.has(o)); //false

上面的代码使用set方法将对象o当做m的一个键,然后又使用get这个方法读取这个键,最后使用delete方法删除了这个键。
作为构造函数,Map也可以接受一个数组作为参数,该数组 的成员是一个个表示键值对的数组。

var map = new Map([["name","lion"],["title","bad agg"]]);
console.log(map.size); //2
console.log(map.has("name")); //true
console.log(map.get("name")); // lion
console.log(map.has("title")); // true
console.log(map.get("title")); // bad agg

如果对同一个键多次赋值,那么后面的值将覆盖前面的值:

let map = new Map();
map.set(1,"lion").set(1,"mouse");
console.log(map.get(1));//mouse

注意: 如果读取一个未知的键,则返回undefined。其次,只有对同一个对象的引用,Map结构才将其视为同一个键。

操作方法与属性:

  • size属性:size属性返回Map结构成员总数。
  • set(key,value):set方法设置key所对应的键值,然后返回整个Map结构,如果key已经有值,则键值会被更新,否则就新生成该键。set方法返回的是Map本身,因此采用链式写法
  • get(key):get方法读取key对应的键值,如果找不到key,然后就返回undefined。
  • delete(key):返回一个布尔值,表示删除是否成功。

例如:

var hello = function (){console.log("hello");}
var map = new Map()
   .set(hello,"hello lion")
   .set("name","lion")
   .set("title","bad agg")
   .set(undefined,"nah"); //链式写法
console.log(map.size); //4
console.log(map.get(hello)); // hello lion
console.log(map.has("title")); // true
console.log(map.has("years")); // false
console.log(map.delete(undefined)); // true
console.log(map.has(undefined)); //false

map.clear();
console.log(map.size); //0

遍历方法:

Map结构所提供的3个遍历器生成函数和1个遍历方法与Set结构基本相同,用法也是类似。

  • keys():返回一个键名的遍历器
  • values():返回一个键值的遍历器
  • entries():返回一个键值对的遍历器
  • forEach():使用回调函数遍历每个成员

如下:

var hello = function (){console.log("hello");}
var map = new Map()
   .set(hello,"hello lion")
   .set("name","lion")
   .set("title","bad agg")
   .set(undefined,"nah");

console.log("keys方法:");
for(let key of map.keys()){
    console.log(key);
}
console.log("values方法:");
for(let value of map.values()){
    console.log(value);
}
console.log("entries方法:");
for(let item of map.entries()){
    console.log(item[0],item[1]);
}
//或者
console.log("或者:");
for(let [key,value] of map.entries()){
    console.log(key,value);
}

这里写图片描述

其次,Map结构转换为数据结构比较快的方法就是结合使用扩展运算符(…)

let map = new Map([
    [1,'one'],
    [2,'two'],
    [3,'three'],
]);
console.log("keys:"+[...map.keys()]);
console.log("values:"+[...map.values()]);
console.log("entries:"+[...map.entries()]);

结果如下图:
这里写图片描述

3.Map与其他数据结构互相转换

  1. Map转为数组:前面已经说过将Map转化为数组最方便的方法了,那就是使用扩展运算符(…)。

  2. 数组转为Map:将数组传入Map构造函数就可以转为Map

let map = new Map([
    [1,'one'],
    [2,'two'],
    [3,'three'],
]);
console.log([...map]); //  [Array(2), Array(2), Array(2)]
  1. Map转为对象:如果Map的所有键都是字符串,则其可以转化为对象
function strMapToObj(str){
    let obj = Object.create(null);
    for(let [k,v] of str){
        obj[k] = v;
    }
    return obj;
}
let myMap = new Map().set('yes',true).set('no',false);
var ob = strMapToObj(myMap);
console.log(ob); //Object {yes: true, no: false}
  1. 对象转为Map
function strMapToObj(obj){
    let str = new Map();
    for(let k of Object.keys(obj)){
        str.set(k,obj[k]);
    }
    return str;
}

var ob = {yes:true,no:false};
console.log(strMapToObj(ob)); 
//Map(2) [['yes',true],['no',false]]
  1. Map转为JSON:Map转化为JSON要区分两种情况,一是Map的键名都是字符串,这时可以选择转为对象JSON
//情况一:
function strMapToJson(str){
    return JSON.stringify(strMapToObj(str));
}
let myMap = new Map().set('yes',true).set('no',false);

var oj = strMapToJson(myMap);
console.log(oj); //{"yes":true,"no":false}

//情况二
function mapToArrayJson(map){
    return JSON.stringify([...map]);
}
let myMap = new Map().set(true,7).set({foo:3},["axc"]);
console.log(mapToArrayJson(myMap));
//[[true,7],[{"foo":3},["axc"]]]
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值