字典 是一种以键-值对形式存储数据的数据结构,像电话簿里面的电话和号码一样,本文字典的的基础类为Array.
字典实现:
-
function Dictionary() {
-
this.datastore = [];
-
this.add = add;
-
this.find = find;
-
this.remove = remove;
-
this.showAll = showAll;
-
this.count = count;
-
this.clear = clear;
-
this.kSort = kSort;
-
this.vSort = vSort
-
}
-
//添加
-
function add(key,value) {
-
this.datastore[key] = value;
-
}
-
//查找
-
function find(key) {
-
return this.datastore[key];
-
}
-
//删除
-
function remove(key) {
-
delete this.datastore[key];
-
}
-
//显示所有键值对
-
function showAll() {
-
for (var key in this.datastore) {
-
console.log(key + ':' + this.datastore[key]);
-
}
-
}
-
//计数
-
function count() {
-
var n = 0;
-
for (var key in Object.keys(this.datastore)) {
-
n++;
-
}
-
return n;
-
}
-
//清空字典
-
function clear() {
-
for (var key in this.datastore) {
-
delete this.datastore[key];
-
}
-
}
-
// 按键(key)排序,升序
-
function kSort(){
-
var dic = this.datastore;
-
var res = Object.keys(dic).sort();
-
for(var key in res ){
-
console.log(res[key] + " : " + dic[res[key]]);
-
}
-
}
-
// 按键(key)排序,降序
-
function vSort(){
-
var dic = this.datastore;
-
var res = Object.keys(dic).sort(function(a,b){
-
return dic[a]-dic[b];
-
});
-
for(var key in res ){
-
console.log(res[key] + " : " + dic[res[key]]);
-
}
-
}
-
-
var pbook = new Dictionary();
-
//添加键值对
-
pbook.add("Mike","123");
-
pbook.add("David", "345");
-
pbook.add("Cynthia", "456");
-
pbook.add("Cyntddhia", "456");
-
//显示所有数据
-
pbook.showAll();
-
//显示数量
-
pbook.count();
-
//排序
-
pbook.vSort()
'
运行
Map 结构的实例有以下属性和操作方法
(1)size 属性
size
属性返回 Map 结构的成员总数。
-
const map = new Map();
-
map.set('foo', true);
-
map.set('bar', false);
-
-
map.size // 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
-
m.has('years') // false
-
m.has(262) // true
-
m.has(undefined) // 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
'
运行
遍历方法
Map 结构原生提供三个遍历器生成函数和一个遍历方法。
-
keys()
:返回键名的遍历器。 -
values()
:返回键值的遍历器。 -
entries()
:返回所有成员的遍历器。 -
forEach()
:遍历 Map 的所有成员。
需要特别注意的是,Map 的遍历顺序就是插入顺序。
-
const map = new Map([
-
['F', 'no'],
-
['T', 'yes'],
-
]);
-
-
for (let key of map.keys()) {
-
console.log(key);
-
}
-
// "F"
-
// "T"
-
-
for (let value of map.values()) {
-
console.log(value);
-
}
-
// "no"
-
// "yes"
-
-
for (let item of map.entries()) {
-
console.log(item[0], item[1]);
-
}
-
// "F" "no"
-
// "T" "yes"
-
-
// 或者
-
for (let [key, value] of map.entries()) {
-
console.log(key, value);
-
}
-
// "F" "no"
-
// "T" "yes"
-
-
// 等同于使用()
-
for (let [key, value] of map) {
-
console.log(key, value);
-
}
-
// "F" "no"
-
// "T" "yes"
'
运行
上面代码最后的那个例子,表示 Map 结构的默认遍历器接口(属性),就是
entries
方法。
-
map[Symbol.iterator] === map.entries
-
// true
Map 结构转为数组结构,比较快速的方法是使用扩展运算符(...
)。
-
const map = new Map([
-
[1, 'one'],
-
[2, 'two'],
-
[3, 'three'],
-
]);
-
-
[...map.keys()]
-
// [1, 2, 3]
-
-
[...map.values()]
-
// ['one', 'two', 'three']
-
-
[...map.entries()]
-
// [[1,'one'], [2, 'two'], [3, 'three']]
-
-
[...map]
-
// [[1,'one'], [2, 'two'], [3, 'three']]
结合数组的map
方法、filter
方法,可以实现 Map 的遍历和过滤(Map 本身没有map
和filter
方法)。
-
const map0 = new Map()
-
.set(1, 'a')
-
.set(2, 'b')
-
.set(3, 'c');
-
-
const map1 = new Map(
-
[...map0].filter(([k, v]) => k < 3)
-
);
-
// 产生 Map 结构 {1 => 'a', 2 => 'b'}
-
-
const map2 = new Map(
-
[...map0].map(([k, v]) => [k * 2, '_' + v])
-
);
-
// 产生 Map 结构 {2 => '_a', 4 => '_b', 6 => '_c'}
'
运行
此外,Map 还有一个forEach
方法,与数组的forEach
方法类似,也可以实现遍历。
-
map.forEach(function(value, key, map) {
-
console.log("Key: %s, Value: %s", key, value);
-
});
forEach
方法还可以接受第二个参数,用来绑定this
。
-
const reporter = {
-
report: function(key, value) {
-
console.log("Key: %s, Value: %s", key, value);
-
}
-
};
-
-
map.forEach(function(value, key, map) {
-
this.report(key, value);
-
}, reporter);
上面代码中,forEach
方法的回调函数的this
,就指向reporter
。
与其他数据结构的互相转换
(1)Map 转为数组
前面已经提过,Map 转为数组最方便的方法,就是使用扩展运算符(...
)。
-
const myMap = new Map()
-
.set(true, 7)
-
.set({foo: 3}, ['abc']);
-
[...myMap]
-
// [ [ true, 7 ], [ { foo: 3 }, [ 'abc' ] ] ]
'
运行
(2)数组 转为 Map
将数组传入 Map 构造函数,就可以转为 Map。
-
new Map([
-
[true, 7],
-
[{foo: 3}, ['abc']]
-
])
-
// Map {
-
// true => 7,
-
// Object {foo: 3} => ['abc']
-
// }
'
运行
(3)Map 转为对象
如果所有 Map 的键都是字符串,它可以无损地转为对象。
-
function strMapToObj(strMap) {
-
let obj = Object.create(null);
-
for (let [k,v] of strMap) {
-
obj[k] = v;
-
}
-
return obj;
-
}
-
-
const myMap = new Map()
-
.set('yes', true)
-
.set('no', false);
-
strMapToObj(myMap)
-
// { yes: true, no: false }
'
运行
如果有非字符串的键名,那么这个键名会被转成字符串,再作为对象的键名。
(4)对象转为 Map
-
function objToStrMap(obj) {
-
let strMap = new Map();
-
for (let k of Object.keys(obj)) {
-
strMap.set(k, obj[k]);
-
}
-
return strMap;
-
}
-
-
objToStrMap({yes: true, no: false})
-
// Map {"yes" => true, "no" => false}
'
运行
(5)Map 转为 JSON
Map 转为 JSON 要区分两种情况。一种情况是,Map 的键名都是字符串,这时可以选择转为对象 JSON。
-
function strMapToJson(strMap) {
-
return JSON.stringify(strMapToObj(strMap));
-
}
-
-
let myMap = new Map().set('yes', true).set('no', false);
-
strMapToJson(myMap)
-
// '{"yes":true,"no":false}'
另一种情况是,Map 的键名有非字符串,这时可以选择转为数组 JSON。
-
function mapToArrayJson(map) {
-
return JSON.stringify([...map]);
-
}
-
-
let myMap = new Map().set(true, 7).set({foo: 3}, ['abc']);
-
mapToArrayJson(myMap)
-
// '[[true,7],[{"foo":3},["abc"]]]'
'
运行
(6)JSON 转为 Map
JSON 转为 Map,正常情况下,所有键名都是字符串。
-
function jsonToStrMap(jsonStr) {
-
return objToStrMap(JSON.parse(jsonStr));
-
}
-
-
jsonToStrMap('{"yes": true, "no": false}')
-
// Map {'yes' => true, 'no' => false}
但是,有一种特殊情况,整个 JSON 就是一个数组,且每个数组成员本身,又是一个有两个成员的数组。这时,它可以一一对应地转为 Map。这往往是 Map 转为数组 JSON 的逆操作。
-
function jsonToMap(jsonStr) {
-
return new Map(JSON.parse(jsonStr));
-
}
-
-
jsonToMap('[[true,7],[{"foo":3},["abc"]]]')
-
// Map {true => 7, Object {foo: 3} => ['abc']}
'
运行