由codewars上的一道題目學習ES6的Map

我對ES6數據結構Map的學習

最近在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入門書籍

認識Map數據結構

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

Map實例的屬性和方法

  • 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數據結構的轉換

  • 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']}

PS:

下面的例子中,字符串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
相關文章
相關標籤/搜索