资讯专栏INFORMATION COLUMN

Set和Map数据结构。

lixiang / 1378人阅读

摘要:本身是一个构造函数,用来生成数据结构。该数组的成员是一个个表示键值对的数组。张三张三事实上,不仅仅是数组,任何具有接口每个成员都是一个双元素的数组的数据结构都剋以当作构造函数的参数。实例的属性和操作方法属性属性返回结构的成员总数。

ES6提供了新的数据结构Set,它类似与数组,但是成员值都是唯一的,没有重复的值。 Set本身是一个构造函数,用来生成Set数据结构。
const s = new Set();
[2,3,5,4,5,2,2].forEach(x=>s.add(x));
for(let i of s){
    console.log(i);//2 3 5 4
}

上面代码通过add()方法向Set结构加入成员,结果表明Set结构不会添加重复的值。
Set函数可以接受一个数组作为参数,用来初始化。

//例子1
const set = new Set([1,2,3,4,4]);
[...set];//[1,2,3,4]
//例子2
const items = new Set([1,2,3,4,5,5,5,5]);
items.size//5
//例子3
const set = new Set(document.querySelectorAll("div"));

上面代码中,例一和例二都是Set函数接受数组作为参数,例三是接受类似数组的对象作为参数。
上面代码也展示了一种去除数组重复成员的方法。

//去除数组的重复成员
[...new Set(array)]
//去除字符串里面的重复字符
[...new Set("ababbc")].join("");//"abc"
//下面代码向Set实例添加了两个NaN,但是只能加入一个。这表明在Set内部两个NaN是相等。
let set = new Set();
let a = NaN;
let b = NaN;
set.add(a);
set.add(b);
set // Set {NaN}
//另外,两个对象总是不相等的。
let set = new Set();
set.add({});
set.size // 1
set.add({});
set.size // 2
Set实例的属性和方法

Set结构的实例有以下属性。

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

Set实例的方法分为两大类:操作方法和遍历方法。下面先介绍四个操作方法。

-add(value):添加某个值,返回Set结构本身。
-delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
-has(value):返回一个布尔值,表示该值是否为Set的成员。
-clear();清除所有成员,没有返回值。

下面这些属性和方法的示例如下:

s.add(1).add(2).add(2);
//注意2被加入了两次
s.size//2
s.has(1)//true
s.has(2)//true
s.has(3)//false
s.delete(2);
s.has(2)//false

下面是一个对比,看看在判断是否包括一个键上面,Object结构和Set结构的写法不同。

//对象的写法
const properties ={
    "width":1,
    "height":1
};
if(properties[someName]){
    //do something
}
//Set的写法
const properties = new Set();
properties.add("width");
properties.add("height");
if(properties.has(someName)){
    //do something
}

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

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

这就提供了去除数组重复成员的另一种方法。

function dedupe(array){
    return Array.from(new Set(array));
};
dedupe([1,1,2,3])//[1,2,3]
遍历操作

Set 结构的实例有四个遍历方法,可以用于遍历成员。

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

(1)keys(),value(),entries()
keys方法、values方法、entries方法返回的都是遍历器对象。由于Set结构没有键名,只有键值所以keys方法和values方法的行为完全一致。

let set = new Set(["red","green","blue"]);
for(let item of set.keys){
    console.log(items);//red,grren,blue
}
for(let item of set.values){
    console.log(item);//red,green,blue
}
for(let item of set.entries){
    console.log(item)
}
//["red","red"]["green","green"]["blue","blue"]

上面代码中,entries方法返回的遍历器,同时包括键名和键值,所以每次输出一个数组,它的两个成员完全相等。
Set结构的实例默认可遍历,它的默认遍历器生成函数就是它的values方法。

Set.prototype[Symbol.iterator] === Set.prototype.values

这就意味着,可以省略values方法,直接用for...of循环遍历Set。

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

(2)forEach()
Set结构的实例与数组一样,也拥有forEach方法,用于对每个成员执行某种操作,没有返回值。

let set = new Set([1,4,9]);
set.forEach((value,key)=>console.log(key+":"+value))
//1:1 4:4 9:9

上面代码说明,foreach方法的参数就是一个处理函数。该函数的参数与数组的forEach一致,依次为键值、键名、集合本身。这里需要注意,Set结构的键名就是键值,因此第一个参数与第二个参数的值永远都是一样的。另外,forEach方法还可以有第二个参数,表示绑定处理函数内部的this对象。
(3)遍历的应用
扩展运算符(...)内部使用for...of循环,所以也可以使用Set结构。

let set = new Set(["red","green","blue"]);
let arr = [...set];
//["red","green","blue"]
扩展运算符和Set结构相结合,就可以去除数组的重复成员。
let arr = [3,5,2,2,5,5];
let unique = [...new Set(arr)]
//[3,5,2]

而且,数组的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}
Map含义和基本用法

Javascript的对象,本质上是键值对的集合,但是传统上只能用字符串当作键,这给它的使用带来了很大的限制。

const data = {};
const element = document.getElementById("myDiv");
data[element] = "metadata";
data["[object HTMLDivElement]"]//"metadata"

上面代码原意是将一个DOM节点作为对象data的键,但是由于对象只接受字符串作为键名,所以element被自动转为字符串[object HTMLDivElement].
为了解决这个问题,ES6提供了Map数据结构。他类似与对象,也是键值对的集合,但是键的范围不限于字符串,各种类型的值都可以当作键。也就是说,Object结构提供了字符串-值的对应,Map结构提供了值-值的对应,是一种更完善的Hash结构实现。如果你需要键值对的数据结构,Map比Object更合适。

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
m.has(o)//false

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

const map = new Map([
    ["name","张三"],
    ["title","Author"]
]);
map.size//2
map.has("name")//true
map.get("name")//张三
map.has("title")//true
map.get("title")//Author

事实上,不仅仅是数组,任何具有Iterator接口、每个成员都是一个双元素的数组的数据结构都剋以当作Map构造函数的参数。也就是说,Set和Map都可以用来生成新的Map。

const set = new Set([
    ["foo",1],
    ["bar",2]
])
const m1 = new Map(set);
m1.get("foo")//1

const m2 = new Map([["baz",3]]);
const m3 = new Map(m2);
m3.get("baz")//3

上面代码中,我们分别使用set对象和Map对象,当作Map构造函数的参数,结果都生成了新的Map对象。
如果对同一个键多次赋值,后面的值将覆盖前面的值。

const map = new Map();
map.set(1,"aaa")
   .set(1,"bbb")
map,get(1)//"bbb"

上面代码对键1连续赋值两次,后一次的值覆盖前一次的值。
如果读取一个未知的键,则返回undefined。

new Map().get("dsada")//undefined.
实例的属性和操作方法

(1)size属性
size属性返回Map结构的成员总数。

const map = new Map()
map.set("foo",true)
map.set("bar",false)
map.szie//2

(2)set(key,value)
set方法设置键名key对应的键值为value,然后返回整个map结构。如果key已经有值,则键值会被更新,否则就新生成该键。

const m = new Map()
m.set("edition",6);//键是字符串
m.set(262,"standard");//键是数值
m.set(undefined,"nah");//键是undefined

set方法返回的是当前的Map对象,因此剋以采用链式写法。

let map = new Map()
    .set(1,"a")
    .set(2,"b")
    .set(3,"c")

(3)get(key)
get方法读取key对应的键值,如果找不到key,返回undefined。

const m = new Map();
const hello = function(){console.log("hello");};
m.set(hello,"Hello ES6")//键是函数
m.get(hello)//Hello ES6   

(4)has(key)
has方法返回一个布尔值,表示某个键是否在当前Map对象之中。

const m = new Map();
m.set("edition",6);
m.set("262","standard");
m.set(undefined,"nah");
m.has("edition")//true

(5)delete(key)
delete方法删除某个键,返回true,如果删除失败,返回false。

const m = new Map();
m.set(undefined,"nah");
m.has(undefined)//true
m.delete(undefined);
m.has(undefined);//false

(6)clear()
clear方法清除所有成员,没有返回值。

let map = new Map();
map.set("foo",true);
map.set("bar",false);
map.size//2
map.clear();
map.size//0;

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/101620.html

相关文章

  • 深入理解:ES6中的SetMap数据结构Map与其它数据结构的互相转换

    摘要:学习笔记工作中常用到的语法只是简单提及和,今天有空于是写了这篇文章深入理解中的和数据结构,与其它数据结构的互相转换。的提供了新的数据结构。本身是一个构造函数,用来生成数据结构。 文中的内容主要是来自于阮一峰的《ES6标准入门》(第三版)。《学习ES6笔记──工作中常用到的ES6语法》只是简单提及Set和Map,今天有空于是写了这篇文章──《深入理解:ES6中的Set和Map数据结构,M...

    Cristalven 评论0 收藏0
  • 【ES6脚丫系列】Set+WeakSet+Map+WeakMap

    摘要:返回一个布尔值,表示该值是否为的成员。清除所有成员,没有返回值。返回的都是遍历器对象。结构的实例的方法,用于对每个成员执行某种操作,没有返回值。这个特点意味着,无法引用的成员,因此是不可遍历的。数组成员是一个或多个表示键值对的一维数组。 本文字数:4700+,阅读时间约10分钟。 如果有理解不到位的地方,欢迎大家纠错。 一、Set 【01】Set是一种数据结构。类似于数组,但是成员的值...

    lyning 评论0 收藏0
  • 【ES6入门09】:SetMap数据结构

    摘要:类似于与的区别和的对比与对比数据结构横向对比,增查改删增查改删与对比增查改删与对比增查改删建议优先使用,不使用,特别是复杂的数据结构考虑数据唯一性,使用,放弃和 Set 1.add()方法和size属性 { let list = new Set(); // add()方法向Set数据添加元素 list.add(5); list.add(7); /...

    Codeing_ls 评论0 收藏0
  • es6 Mapset

    摘要:返回一个布尔值,表示该值是否为的成员。清除所有成员,没有返回值。该数组中的每一项也必须是数组,内部数组的首个项会作为键,第二项则为对应值。返回所有成员的遍历器需要特别注意的是,的遍历顺序就是插入顺序。 Js大部分历史时期都只存在一种集合类型,也就是数组类型。数组在 JS 中的使用正如其他语言的数组一样,但缺少更多类型的集合导致数组也经常被当作队列与栈来使用。数组只使用了数值型的索引,而...

    superPershing 评论0 收藏0
  • ECMAScript6(11):SetMap

    摘要:的默认遍历器是另外这里需要格外强调的是中的方法是判断键值是否存在的,如中的方法是判断键名是否存在的,如解构转换技巧转转为防止不必要的错误,直接丢弃不是字符串为键的属性转和类似,不过它只接受对象作为键名,除外。 Set Set 是一种集合结构,特征和数学中的一致,具有以下特征: 同一个集合中不能有相同元素 set 可以存放不同类型的数据 但使用过程中请注意以下几点: 存入 set ...

    BothEyes1993 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<