容器!!在JavaScript中,其实并没有特别强调这个东西。
但是,在写程序的过程中,容器有一些特别的技巧可以使用。
在此我们来介绍一下容器与写程序有什么可以使用的技巧吧。
容器Containers
使用容器,可以直接取得一种成熟可靠的数据结构。可以让你更专注于你的问题,而不是在处理数据结构的问题上。
STL将「在数据上执行的操作」与「要执行操作的数据分开」
称为容器的意思,是结构兼容而型别不同的构造。不过JavaScript本来就没有变数型别,所以没有强调这方面,C++倒是就会强调型别的问题。
故事是这样的。
依汇编语言的使用型式造出了C样貌,而「相同型别的连续內存空间」就被称为了「数组」
数组
#include <stdio.h>
#define ArrayLength 10
int main()
{
int array[ArrayLength] = {0,1,2,3,4,5,6,7,8,9};
array[4] = 0;//setter
for(int i = 0;i < ArrayLength;i++){
printf(“%d”,array[i]);//getter
}
return 0;
}
输出
0123056789
优点,就是拥有了抽象数据型别:array
缺点,在执行时期array是不可以变动长度的。对于大型项目来说,內存无法得到善用。
所以,有了「数据结构」这门课!!教教大家从「如何善用內存,又可以保持相同的使用方便性」入手。
循序式容器sequence containers
One common property of all sequential containers is that the elements can be accessed sequentially.[2]
循序式容器,就是非常的像是数组的使用方式,依序存取。
在最初C语言数组,是用「移动指标」的方式实现。也就是「距离开头多远」的方式找到该元素。
索引方式:只能使用数字
C++代表性的循序式容器:vector,list
关联式容器associative containers
关联式容器,要做到随机存取,意思是说,存取任何一个元素所花费的时间将会是固定的。
每个元素是由一组key-value组成,称为一个pair,在C++中,是确实有这样的型别,但是在JavaScript中,只是一个(两个元素)的数组。所有元素的key不可以重复
在索引方式会创造一棵树[3](vmwork)
每次使用setter时,会重新计算树,并且将pair储存起来。
每次使用getter时,会走访这颗树,并且经过固定长度的节点,将树走完,并且取得值。
索引方式:可使用文字或数字
(建议使用文字就好)
C++代表性的关联式容器:set,map
利用容器写程序
if(apiData.status === 1){
project.status =“start”
}
else if(apiData.status === 2){
project.status =“processing”
}
else if(apiData.status === 3){
project.status =“staged”
}
else if(apiData.status === 4){
project.status =“finish”
}
else if(apiData.status === 0){
project.status =“error”
}
消除这个if-else
const status = [
“error”,
“start”,
“processing”,
“staged”,
“finish”,
]
project.status = status[apiData.status]
为什么可以这样做呢?
其实if-else里,与容器透过索引值找到内容的方法相同,再看一次如下
if(apiData.status === 0 + 1){
project.status =“start”
}
else if(apiData.status === 0 + 2){
project.status =“processing”
}
else if(apiData.status === 0 + 3){
project.status =“staged”
}
else if(apiData.status === 0 + 4){
project.status =“finish”
}
else if(apiData.status === 0 + 0){
project.status =“error”
}
反过来呢?
if(apiData.status ===“start”){
project.status = 1
}
else if(apiData.status ===“processing”){
project.status = 2
}
else if(apiData.status ===“staged”){
project.status = 3
}
else if(apiData.status ===“finish”){
project.status = 4
}
else if(apiData.status ===“error”){
project.status = 0
}
再消除一次这个if-else
const status = {
“error”:0,
“start”:1,
“processing”:2,
“staged”:3,
“finish”:4,
}
project.status = status[apiData.status]
为什么可以这样做呢?
关联式容器在key-value找值的过程,做了很多的判断。(它有写if-else了),所以可以利用这个容器特性省掉一些不必要的if-else变成代码冗赘的语法。
消除重复(leafor)
在此就要特别介绍一下Set每个元素,都当作key。也就是不重复元素的list或array。
如果在C++中,这个问题也不用像我以前不懂事这样写一堆code[4]
std::vector<int> vch;
//…
std::sort(vch.begin(),vch.end());//排序
eraseit = std::unique(vch.begin(),vch.end());//排不重覆元素
vch.erase(eraseit,vch.end());//没被排到的删掉
输出
0,0,1,2,2,2,3,3,3,5,5,6,6,6,6,6,7,7,9,9,
0,1,2,3,5,6,7,9,3,5,5,6,6,6,6,6,7,7,9,9,
0,1,2,3,5,6,7,9,
后来都这样写
show(vch);
std::set<int> sch(vch.begin(),vch.end());
show(sch);
std::vector<int> cloneVch(sch.begin(),sch.end());
show(cloneVch);
输出
3,6,7,5,3,5,6,2,9,1,2,7,0,9,3,6,0,6,2,6,
0,1,2,3,5,6,7,9,
0,1,2,3,5,6,7,9,
看起来好像也不差。
有时会用if-else判断是否已存在就不用讲了。
在JavaScript中
ES5的标准中,想用关联式容器就用{},想用循序式容器用[]
ES6的标准已经有Set可以用,来看看两者的比较[5]
ES6的写法,不用自己写if啰
let s = new Set()
s.add(“hello”).add(“goodbye”).add(“hello”)
s.size === 2
s.has(“hello”)=== true
for(let key of s.values())// insertion order
console.log(key)
用ES5的写法就是有if。
var s = {};
s[“hello”] = true;s[“goodbye”] = true;s[“hello”] = true;
Object.keys(s).length === 2;
s[“hello”] === true;
for(var key in s)// arbitrary order
if(s.hasOwnProperty(key))
console.log(s[key]);
虽然,不写就不是不存在(本来就必须存在),但是要利用它的if逻辑,也许自己的代码可以保持某种程度的简洁(狂热!!!)