--- tags: A&D, data-structure, JavaScript --- # JavaScript 初探 A&D - 資料結構 Map `Map` 是 JavaScript 在 ES6 推出的新物件,讓 JavaScript 工程師有合適的工具可以表達其他語言中 `Map` 的資料結構。 ## Baisc Usage `Map` 可以透過 `new Map()` 建構出來: ```javascript= let m = new Map() ``` 設定初始化資料: ```javascript= const m = new Map([['b', 2],['c',3]]) ``` 透過 `.set()` `.get()` `.has()` `.delete()`去存取、確認、刪除資料: ```javascript= m.set('a',1) // m.set(key,val) , Map(1) { 'a' => 1} m.get('a') // m.get(key) ,1 m.has('a') // m.has(key) ,true m.delete('a') //m.delete(key) , true ``` 也可以透過 `.clear()` 去清空資料 ```javascript= m.clear() // undefined ``` .size() 取得總數 ```javascript= m.size() // 0 => .clear() 全清掉了 ``` 此外,他跟 `Obejct` 一樣可以透過 `.keys()` `.values()` 取得全部的 key,value。 ```javascript= const m = new Map([['b', 2],['c',3]]) m.keys() // [Map Iterator] { 'b', 'c' } m.values() //[Map Iterator] { 2, 3 } let mKeys = [...m.keys()] // 轉array [ 'b', 'c' ] ``` ## vs Object 一般在 JavaScript 裡說到 key pair value 直覺就會想到 `Object`,但 `Map` 跟 `Object` 還是有一些差別的 1. `Map` 的 `keys` 可以是**任意值** , `Object` 只能是 `string` 或 `symbols`: ```javascript= const func = ()=>{} console.log(m.set(func,1)) console.log(m.get(func)) // 1 const obj = { func:1 // {'func':1} ,func 是 string 不是 function } ``` 2. `Map` 的 keys 會根據被添加的時間而有順序性,`Object` 沒有 3. `Map` 可直接迭代, `Object` 需用 `Object.keys()` 將 key 轉為 array 才能用 ```javascript= //map for (let k of m.keys()) { console.log(k) } //object => for..in.. 迭代 for(let k in Object.keys(obj)){ console.log(k) } ``` 4. `Map` 的檢索效率高於 `Object` 5. `Map` 繼承至 `Object`(幾乎所有實體都是,包含 `array`),所以 `Map` 可以使用所有 `Object` 的功能,但反之`Object` 則不行。 ```javascript= let m = new Map([[1,2],[3,4]]); console.log(map instanceof Object); //true let obj = new Object(); console.log(obj instanceof Map); //false ``` ### `Object`、`Map` 的使用時機 #### `Map` - 具有順序性的資料 - 經常增添刪減屬性 - 需要迭代 #### `Object` - 簡單的資料 - 需要轉變為 `JSON` ## with Algorithm 那 `Map` 到底可以用在哪裡,用經典的 [leetcode - 1 Two sum](https://leetcode.com/problems/two-sum/) 來示範 > 題目說明: function 接收2個參數 array 和 target 在 array 裡找到可以2個組合成 target 的 item 並回傳 index >limit: 1.不能使用同一個 idx 組成 ex: [1,1] 2.只回傳一個答案 >example: Input: nums = [2,7,11,15], target = 9 Output: [0,1] Explanation: Because nums[0] + nums[1] == 9, we return [0, 1]. ```javascript= // BigO(n) const twoSum = function(nums, target) { if(nums.length <2){ return [] } const m = new Map() let ans = [] nums.forEach((item,idx)=>{ let diff = target - item if(m.has(diff)){ // 檢測這個 diff 有沒有在 map 裡 ans = [idx,m.get(diff)] // 有的話將當下的 index 和記錄在 map 裡得 index 回傳給 ans }else{ m.set(item,idx) // 沒有的話就將當前的 [item, index] 存進 map } }) return ans } ``` 另一題 [1122. Relative Sort Array](https://leetcode.com/problems/relative-sort-array/) 有採用到 `Map` 的順序性來解決問題 > 題目說明: function 接收2個 array , arr1 和 arr2 將 arr1 裡的值依照 arr2 的順序排序 >limit: 1.arr2 的值不會重複 2.如果 arr1 值不在 arr2 裡 將依大小排到最後面 >example: Input: arr1 = [28,6,22,8,44,17], arr2 = [22,28,8,6] Output: [22,28,8,6,17,44] ```javascript= // BigO(2n) var relativeSortArray = function(arr1, arr2) { // 將 Map 依照 arr2 的順序建立 const count = new Map(arr2.reduce((acc,curr)=>[...acc,[curr,0]],[])); const result = []; // 將 arr1 小 -> 大排序 arr1.sort((a, b) => a - b); // Map 計算 item count arr1.forEach(item => count.has(item) ? count.set(item, count.get(item) + 1) : count.set(item, 1)) // 將結果輸出到 result count.forEach((val, key) => { for(let i = 0; i< val; i++){ result.push(key) } }) return result; }; ``` # 參考資料 https://flaviocopes.com/javascript-data-structures-map/ https://pjchender.dev/javascript/js-map/ https://medium.com/front-end-weekly/es6-map-vs-object-what-and-when-b80621932373 https://ithelp.ithome.com.tw/articles/10227715