

文章目录
前文的学习过程中,我们已经了解了非常多的数据类型,包括基础类型、复杂的对象、顺序存储的数组等。为了更好的应对现实生产中的情况,我们还需要学习更多的数据类型:映射(Map)和集合(Set)。
Map是一个键值对构成的集合,和对象非常相似,都是由一个名称对应一个值组成的。Map和对象区别在于,Map的键可以采用任何类型的数据,而对象只能使用字符串作为属性名称。
new Map()——创建Map对象;map.set(key, val)——添加一个键值对;map.get(key)——通过键找到val值,如果不存在key,返回undefined;map.has(key)——判断map是否存在键key,存在返回true,不存在返回false;map.delete(key)——删除指定键;map.clear()——清空map中所有的内容;map.size——map中键值对的数量;举个例子:
let map = new Map()//创建一个空的Map
map.set('name','xiaoming') //字符串作为键
map.set(3120181049,'ID') //数字作为键
map.set(true,'Bool') //bool作为键
console.log(map.get('name'))//xiaoming
console.log(map.has(true)) //true
console.log(map.delete(true))//删除true键
console.log(map.size) //2
console.log(map.clear()) //清空
console.log(map.size) //0
代码执行结果:

map.set(key, val)方法返回map本身。
虽然map[key]方式同样可以访问映射的键值对,但是不推荐使用这种方式,因为它会造成歧义。我们可以看下面的案例:
let map = new Map()
map[123] = 123 //创建一个键值对
console.log(map[123])//123
console.log(map['123'])
这里就出现了一个奇怪的结果:

不仅使用键123还可以使用'123'访问数据。
甚至,如果我们使用map.set()和map[]混用的方式,会引起程序错误。
在JavaScript中,如果我们对映射使用了map[key]=val的方式,引擎就会把map视为plain object,它暗含了对应所有相应的限制(仅支持String、Symbol键)。
所以,我们不要使用map[key]的方式访问Map的属性!!
由于Map对键的类型不做任何限制,我们还可以把对象当作键值使用:
let clazz = {className:'9年1班'}
let school = new Map()
school.set(clazz,{stu1:'xiaoming',stu2:'xiaohong'})
console.log(school.get(clazz))
代码执行结果:

在对象中,对象是不能作为属性名称存在的,如果我们把对象作为属性名,也会发生奇怪的事:
let obj = {}
let objKey = {key:'key'}
obj[objKey] = 'haihaihai'
console.log(obj['[object Object]'])
代码执行结果:

发生这种现象的原因也非常简单,对象会把非字符串、Symbol类型的属性名转为字符串类型,对象相应的就转为'[object Object]'了,于是对象中就出现了一个名为'[object Object]'的属性。
Map键值比较方法
Map使用SameValueZero算法比较键值是否相等,和===差不多,但是NaN和NaN是相等的,所以NaN也可以作为键使用!
链式调用
由于
map.set返回值是map本身,我们可以使用如下调用方式:map.set(1,1) .set(2,2) .set(3,3)
我们可以在以下三个函数的帮助下完成映射的迭代:
map.keys()——返回map所有键的可迭代对象;map.values()——返回map所有值的可迭代对象;map.entries()——返回map所有键值对的可迭代对象;举个栗子:
let map = new Map([
['key1',1],
['key2',2],
['key3',3],
])
//遍历所有的键
for(let key of map.keys()){
console.log(key)
}
//遍历所有的值
for(let val of map.values()){
console.log(val)
}
//遍历所有的键值对
for(let ky of map.entries()){
console.log(ky)
}
代码执行结果:

遍历的顺序
遍历的顺序和元素插入顺序是相同的,这是和对象的区别之一。
实际上,我们很少使用map.entries()方法遍历Map中的键值对,因为map.entries()是map的默认遍历方式,我们可以直接使用如下代码:
let map = new Map([
['key1',1],
['key2',2],
['key3',3],
])
for(let kv of map){
console.log(kv)
}
代码执行结果:

我们还可以通过Map内置的forEach()方法,为每个元素设置一个遍历方法,就像遍历数组一样。
举例如下:
let map = new Map([
['key1',1],
['key2',2],
['key3',3],
])
map.forEach((val,key,map)=>{
console.log(`${key}-${val}`)
})
代码执行结果:

可能童鞋们已经发现了,在上面的案例中,我们使用了一种独特的初始化方式(没有使用set方法):
let map = new Map([
['key1',1],
['key2',2],
['key3',3],
])
我们通过向new Map()传入一个数组,完成了快速的映射创建。
我们还可以通过Object.entires(obj)方法将对象转为数组,该数组的格式和Map需要的格式完全相同。
举个例子:
let obj = {
xiaoming:'heiheihei',
xiaohong:'hahahahah'
}
let map = new Map(Object.entries(obj))
console.log(map)
代码执行结果:

Object.entries(obj)会返回obj对应的数组:[['xiaoming':'heiheihei'],['xiaoming':'hahahahah']]。
Object.fromEntries()和Object.entries()功能相反,可以把数组和Map转为对象。
数组转对象:
let obj = Object.fromEntries([
['key1','val1'],
['key2','val2'],
['key3','val3'],
])
console.log(obj)
代码执行结果:

Map转对象:
let map = new Map()
map.set('key1','val1')
.set('key2','val2')
.set('key3','val3')
let obj = Object.fromEntries(map)
console.log(obj)
代码执行结果:

map.entries()会返回映射对应的键值对数组,我们也可以使用一种稍微麻烦的方式:
let obj = Object.fromEntries(map.entries())
以上两种方式作用完全相同,建议选择更为简短的方式。
Set是一系列值的集合(注意没有键),我们可以简单的把集合看作一个框,什么值都可以直接扔进去,但是每个值都只能出现一次。
常用的方法:
new Set([iter])——创建一个集合,如果传入了一个可迭代变量(例如数组),就使用这个变量初始化集合set.add(val)——向集合中添加一个元素valset.delete(val)——删除集合中的valset.has(val)——判断集合中是否存在val,存在返回true,否则返回falseset.clear()——清空集合中所有的元素set.size——返回集合中元素的数量集合使用案例:
let set = new Set()
let xiaoming = {name:'xiaoming'}
let xiaohong = {name:'xiaohong'}
let xiaojunn = {name:'xiaojunn'}
set.add(xiaoming)
set.add(xiaohong)
set.add(xiaojunn)
console.log(set)
代码执行结果:

虽然
Set的功能很大程度上可以使用Array代替,但是如果使用arr.find判断元素是否重复,就会造成巨大的性能开销。所以我们需要在合适的场景使用合适的数据结构,从而保证程序的效率。
集合的迭代非常简单,我们可以使用for...of和forEach两种方式:
let set = new Set(['xiaoming','xiaohong','xiaoli'])//使用数组初始化集合
for(let val of set){
console.log(val)
}
set.forEach((val,valAgain,set)=>{
console.log(val)
})
代码执行结果:

注意,使用
forEach遍历集合时,和map一样有三个参数,而且第一个和第二个参数完全相同。这么做的目的是兼容Map,我们可以方便的使用集合替换Map而程序不会出错。
在Map中使用的方法,Set同样适用:
set.keys()——返回一个包含所有值的可迭代对象set.values()——返回值和set.keys()完全相同set.entries()——返回[val,val]可迭代对象看起啦这些方法有些功能上的重复,很奇怪。实际上,和forEach一样,都是为了和Map兼容。
Map 是一个带键的数据项的集合。
常用方法:
new Map([iter]) —— 创建 map,可选择带有 [key,value] 对的 iterable(例如数组)来进行初始化;map.set(key, val) —— 根据键存储值,返回 map 自身,可用于链式插入元素;map.get(key) —— 根据键来返回值,如果 map 中不存在对应的 key,则返回 undefined;map.has(key) —— 如果 key 存在则返回 true,否则返回 false;map.delete(key) —— 删除指定键对应的值,如果在调用时 key 存在,则返回 true,否则返回 false;map.clear() —— 清空 map中所有键值对 ;map.size —— 返回键值对个数与普通对象 Object 的不同点主要是任何类型都可以作为键,包括对象、NaN。
Set —— 是一组值的集合。
常用方法和属性:
new Set([iter]) —— 创建 set,可选择带有 iterable(例如数组)来进行初始化。set.add(value) —— 添加一个值(如果 value 存在则不做任何修改),返回 set 本身。set.delete(value) —— 删除值,如果 value 在这个方法调用的时候存在则返回 true ,否则返回 false。set.has(value) —— 如果 value 在 set 中,返回 true,否则返回 false。set.clear() —— 清空 set。set.size —— 元素的个数。在 Map 和 Set 中迭代总是按照值插入的顺序进行的,所以我们不能说这些集合是无序的,但是我们不能对元素进行重新排序,也不能直接按其编号来获取元素。
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击
有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳
我不知道为什么,但是当我设置这个设置时它无法编译设置:static_cache_control,[:public,:max_age=>300]这是我得到的syntaxerror,unexpectedtASSOC,expecting']'(SyntaxError)set:static_cache_control,[:public,:max_age=>300]^我只想将“过期”header设置为css、javaascript和图像文件。谢谢。 最佳答案 我猜您使用的是Ruby1.8.7。Sinatra文档中显示的语法似乎是在Ruby1.
我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------
本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01 客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02 数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit
文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co
1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,