前言
本人是一个刚入行的菜鸡前端程序员,写这个文章的目的只是为了记录自己学习的笔记与成果,如有不足请大家多多指点。 在集合中,我们感兴趣的是每个值本身,并把它当作主要元素。在字典(或映射)中,我们用[键,值]对的形式来存储数据。
字典
我们已经知道,集合表示一组互不相同的元素(不重复的元素)。在字典中,存储的是[键,值]对,其中键名是用来查询特定元素的。字典和集合很相似,集合以[值,值]的形式存储元素,字典则是以[键,值]的形式存储元素。字典也称作映射、符号表或关联数组。
创建字典类
与set相似,ECMAscript2015同样包含了一个 Map 类的实现,即我们所说的字典。
我们要实现的类就是以 Map 类的实现为基础的。你会发现它和set类很相似,但不同于[值,值]对的形式,我们要存储的是[键,值]对。
//首先声明一个 defaultToString 函数,用来保证所有的键名都是字符串
function defaultToString(item) {
if(item === null) {
return 'NULL'
} else if (item === undefined) {
return 'UNDEFINED'
} else if ( typeof item === 'string' || items instanceof String) {
return `${item}`
}
return item.toString()
}
//声明字典类
class Dictionary() {
constructor(toStrFn = defaultToString) {
this.toStrFn = toStrfn
this.table ={}
}
}
// 声明一个 ValuePair 类
class ValuePair {
constructor (key, value) {
this.key = key
this.value = value
}
toString() {
return `[#${this.key}: ${this.value}]`
}
}
为了在字典中保存value,我们将key转化为了字符串,而为了保存信息的需要,我们同样要保存原始的 key。因此,我们不是只将 value 保存在字典中,而是要保存两个值:原始的key 和 value。为了字典能更简单的通过 toString 方法输出结果,我们同样要为 ValuePair 类创建 toString 方法。
检测一个键是否存在于字典中 - hasKey()
hasKey(key) {
return this.table(this.toStrFn(key)) != null
}
在字典和 ValutPair 类中设置键和值 - set()
set(key, value) {
if(key != null && value != null) {
const tableKey = this.toStrFn(key)
this.table[tableKey] = new ValuePair(key, value)
return true
}
return false
}
从字典中移除一个值 - remove()
remove(key) {
if (this.hasKey(key)) {
delete this.table[this.toStrFn(key)]
return true
}
return false
}
从字典中检索一个值 - get()
get(key) {
const valuePair = this.table[this.toStrFn(key)]
return valuePair == null ? undefined : valuePair.value()
}
我们也可以先验证我们要获取的value是否存在,如果存在,我们就在 table 对象中找到它并返回。
get(key) {
if(this.hasKey(key)) {
return this.table[this.toStrFn(key)]
}
return undefined
}
但是在第二种方法中,我们会获取两次 key 的字符串以及访问两次 table 对象。第一种方式直接返回了value值,第二种方式返回的是一个对象。所以第一种方式的消耗更少,效率更高。
keys、values 和 valuePairs 方法
我们已经给 Dictionary 类创建了最重要的方法,现在来创建一些很有用的辅助方法。
keyValues()
以数组的形式返回字典中的所有 valuePair 对象。
keyValues() {
return Object.values(this.table)
}
我们也可以这样写
keyValues() {
const valuePair = []
for (const k in this.table) {
if(this.hasKey(k)) {
valuePair.push(this.table[k])
}
}
return valuePairs
}
keys()
返回Dictionary类中用于识别值得所有(原始)键名
keys() {
return this.keyValues().map(ValuePair => valuePair.key)
}
values()
返回ValuePair类的value属性。
values() {
return this.keyValues().map( valuePair => valuePair.value)
}
clear、size、isEmpty 和 toString 方法
size() - 返回字典中的值的个数
size() {
return Object.keys(this.table).length
}
isEmpty() - 检查字典是否为空
isEmpty() {
return this.size() === 0
}
clear() - 清空字典
clear() {
this.table = {}
}
toString()
toString() {
if(this.isEnpty()) {
return ''
}
const valueParis = this.keyValue()
let objString = `${valuePairs[0].toString()}`
for(let i = 0; i < valuePairs.length; i++) {
objString = `${objString},${valuePairs[i].toString}`
}
return objString
}
ES2015 Map 类
ECMAscript2015 新增了Map类。可以基于ES2015的 Map 类开发我们的 Dictionary 类。
const map = new Map()
map.set('Gandalf', 'gandalf@email.com')
map.set('John', 'johnsnow@email.com')
map.set('Tyrion', 'tyrion@email.com')
console.log(map.has('Gandalf')) //true
console.log(map.size) //3
console.log(map.keys()) // {"Gandalf", "John", "Tyrion"}
console.log(map.values()) //{"gandalf@email.com", "johnsnow@email.com", "tyrion@email.com"}
console.log(map.get('Tyrion')) //tyrion@email.com
和我们自己写的 Dictionary 类不同,ES2015 的 Map 类的 values 方法和 keys 方法都返回 Iterator ,而不是值或键构成的数组。另一个区别是,我们实现的 size 方法返回字典中存储元素的个数,而 Map 类则有一个 size 属性。
删除 map 中的元素可以用 delete 方法
map.delete('John')
clear 方法会重置 map 数据结构。
小结
在本篇中,我们学习了字典的相关知识,了解了如何添加、移除和获取元素以及其他一些方法。我们还了解了字典和集合的不同之处。我们还学习了如何使用 ES2015 的 Map 类。
在下一篇中,我们将学习递归。