博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Set和Map数据结构。
阅读量:6162 次
发布时间:2019-06-21

本文共 5790 字,大约阅读时间需要 19 分钟。

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函数可以接受一个数组作为参数,用来初始化。

//例子1const set = new Set([1,2,3,4,4]);[...set];//[1,2,3,4]//例子2const items = new Set([1,2,3,4,5,5,5,5]);items.size//5//例子3const 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 // 1set.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//2s.has(1)//trues.has(2)//trues.has(3)//falses.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)//truem.delete(o)//truem.has(o)//false

上面代码使用Map结构set方法,将对象o当作m的一个键,然后又使用get方法读取这个键,接着使用delete方法删除这个键。

上面的例子展示了如何向Map添加成员。作为构造函数,Map也可以接受一个数组作为参数。该数组的成员是一个个表示键值对的数组。

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

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

const set = new Set([    ['foo',1],    ['bar',2]])const m1 = new Map(set);m1.get('foo')//1const 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)//truem.delete(undefined);m.has(undefined);//false

(6)clear()

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

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

转载地址:http://arefa.baihongyu.com/

你可能感兴趣的文章
好记心不如烂笔头,ssh登录 The authenticity of host 192.168.0.xxx can't be established. 的问题...
查看>>
使用addChildViewController手动控制UIViewController的切换
查看>>
Android Fragment应用实战
查看>>
SQL Server查询死锁并KILL
查看>>
内存或磁盘空间不足,Microsoft Office Excel 无法再次打开或保存任何文档。 [问题点数:20分,结帖人wenyang2004]...
查看>>
委托到Lambda的进化: ()=> {} 这个lambda表达式就是一个无参数的委托及具体方法的组合体。...
查看>>
apache 伪静态 .htaccess
查看>>
unity3d 截屏
查看>>
ASP.NET MVC学习之控制器篇
查看>>
MongoDB ServerStatus返回信息
查看>>
分析jQuery源码时记录的一点感悟
查看>>
程序局部性原理感悟
查看>>
UIView 动画进阶
查看>>
Spring如何处理线程并发
查看>>
linux常用命令(用户篇)
查看>>
获取组件的方式(方法)
查看>>
win2008 server_R2 自动关机 解决
查看>>
我的友情链接
查看>>
在C#调用C++的DLL简析(二)—— 生成托管dll
查看>>
Linux macos 常用终端操作
查看>>