最近在CodeWars上作了一道题目,嗯,我这个渣渣没有作出来,而后看了别人的解决方案,Map???javascript
是时候学习一下ES6的Map了。。。。。java
如下是原题:(https://www.codewars.com/kata...)git
Description:es6
You have a positive number n consisting of digits. You can do at most one operation: Choosing the index of a digit in the number, remove this digit at that index and insert it back to another place in the number.数组
Doing so, find the smallest number you can get.数据结构
Task:函数
Return an array or a tuple depending on the language (see "Your Test Cases" Haskell) with学习
1) the smallest number you got
2) the index i of the digit d you took, i as small as possible
3) the index j (as small as possible) where you insert this digit d to have the smallest number.this
Example:prototype
smallest(261235) --> [126235, 2, 0]
126235 is the smallest number gotten by taking 1 at index 2 and putting it at index 0
smallest(209917) --> [29917, 0, 1]
[29917, 1, 0] could be a solution too but index i
in [29917, 1, 0] is greater than
index i
in [29917, 0, 1].
29917 is the smallest number gotten by taking 2 at index 0 and putting it at index 1 which gave 029917 which is the number 29917.
smallest(1000000) --> [1, 0, 6]
如下就是某人的解决方案:
Array.prototype.move = function(from, to) { this.splice(to, 0, this.splice(from, 1)[0]); return this; }; function smallest(n) { let iter = `${n}`.length, res = new Map(); //使用ES6的模板字符串还有Map数据结构 for (let i = 0; i < iter; i++) { for (let j = 0; j < iter; j++) { let number = `${n}`.split('').move(i, j).join(''); //排列组合???哈哈 if (!res.has(+number)) res.set(+number, [i, j]); //添加键值对到Map } } let min = Math.min(...res.keys()); //res.keys()获得键名的遍历器,而后扩展运算符转化为数组,而后最小的number return [min, ...res.get(min)]; //res.get(min)获得对应键名的键值 }
如下内容来自大神博客:阮一峰ES6入门书籍
JavaScript的对象(Object),本质上是键值对的集合(Hash结构),可是传统上只能用字符串看成键。这给它的使用带来了很大的限制。
Map数据结构相似于对象,也是键值对的集合,可是键的范围不限于字符串,各类类型的值均可以做为键。若是你须要“键值对”的数据结构,Map比Object更合适。
var m = new Map(); var o = {p: 'hello world'}; m.set(0, 'connect'); m.get(0); //'connect' m.has(0); //true m.delete(o); //true m.has(o); //false
size()
:返回Map结构的成员总数
操做方法
set(key, value)
:设置对应的键值,而后返回整个Map结构。若是key已经有值,则键值会被更新。
var 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');
get(key)
:读取key对应的键值,若是找不到key返回undefined
var m = new Map(); var hello = function() { console.log("hello"); } m.set(hello, "Hello ES6!") // 键是函数 m.get(hello) // Hello ES6!
has(key)
:返回一个布尔值,表示某个键是否在Map数据结构中。
delete(key)
:删除某个键,成功返回true;删除失败返回false。
clear()
:删除全部成员,没有返回值。
遍历方法
keys()
:返回键名的遍历器
values()
:返回键值的遍历器
entries()
:返回全部成员的遍历器
forEach()
:遍历Map的全部成员
let 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); } // 等同于使用map.entries() for (let [key, value] of map) { console.log(key, value); }
Map转换为数组
使用扩展运算符(...)
let mao = new Map().set(true, 7).set({foo: 3}, ['abc']); [...mao]; //[ [true, 7], [{foo: 3}, ['abc']] ]
转换为数组结构以后,结合数组的map()
方法,filter()
方法能够实现Map的遍历和过滤。Map自己没有map和filter方法,可是有一个forEach方法
let map0 = new Map() .set(1, 'a') .set(2, 'b') .set(3, 'c'); let map1 = new Map( [...map0].filter(([k, v]) => k < 3) ); // 产生Map结构 {1 => 'a', 2 => 'b'} let map2 = new Map( [...map0].map(([k, v]) => [k * 2, '_' + v]) ); // 产生Map结构 {2 => '_a', 4 => '_b', 6 => '_c'}
数组转为Map
new Map([[true, 7], [{foo: 3}, ['abc']]]) // Map {true => 7, Object {foo: 3} => ['abc']}
下面的例子中,字符串true和布尔值true是两个不一样的键。
var m = new Map([ [true, 'foo'], ['true', 'bar'] ]); m.get(true) // 'foo' m.get('true') // 'bar'
若是对同一个键屡次赋值,后面的值将覆盖前面的值。
let map = new Map(); map .set(1, 'aaa') .set(1, 'bbb'); map.get(1) // "bbb"
上面代码对键1连续赋值两次,后一次的值覆盖前一次的值。
若是读取一个未知的键,则返回undefined。
new Map().get('asfddfsasadf') // undefined
注意,只有对同一个对象的引用,Map结构才将其视为同一个键。这一点要很是当心。
var map = new Map(); map.set(['a'], 555); map.get(['a']) // undefined
上面代码的set和get方法,表面是针对同一个键,但实际上这是两个值,内存地址是不同的,所以get方法没法读取该键,返回undefined。
由上可知,Map的键其实是跟内存地址绑定的,只要内存地址不同,就视为两个键。这就解决了同名属性碰撞(clash)的问题,咱们扩展别人的库的时候,若是使用对象做为键名,就不用担忧本身的属性与原做者的属性同名。
若是Map的键是一个简单类型的值(数字、字符串、布尔值),则只要两个值严格相等,Map将其视为一个键,包括0和-0。另外,虽然NaN不严格相等于自身,但Map将其视为同一个键。
let map = new Map(); map.set(NaN, 123); map.get(NaN) // 123 这里是同一个键 map.set(-0, 123); map.get(+0) // 123