Map and Set - Lee-hyuna/33-js-concepts-kr GitHub Wiki
์๋ณธ: http://javascript.info/map-set
์๋์ ๊ฐ์ ๋ณต์กํ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ๋ํด ์์๋ณด๋๋ก ํ์.
- Key ์งํฉ์ ์ ์ฅํ๋ Object
- Array ์งํฉ
์์ ๋ฉ์๋๋ก๋ ์ฝ๋ฉํ๊ธฐ ์ด๋ ต๋ค. ๊ทธ๋์ ์ค๋ ๋ฐฐ์๋ณผ ์ฃผ์ ๋ Map
๊ณผ Set
์ด๋ค.
Map
Map
์ Object
์ฒ๋ผ ํค๋ก ์ฐ๊ฒฐ๋ ๋ฐ์ดํฐ ํญ๋ชฉ์ ์งํฉ์ด๋ค. ๊ทธ๋ฌ๋ ์ฃผ์ ์ฐจ์ด์ ์ Map
์ด ๋ชจ๋ ์ข
๋ฅ์ ํค๋ฅผ ํ์ฉํ๋ค๋ ๊ฒ์ด๋ค.
๋ฉ์๋์ ํ๋กํผํฐ๋ ๋ค์๊ณผ ๊ฐ๋ค.
new Map()
โ ๋งต์ ์์ฑํ๋ค.map.set(key, value)
โ key์ value๊ฐ์ ์ ์ฅํ๋ค.map.get(key)
โ key๊ฐ map์ ์๋ ๊ฒฝ์ฐ undefined๋ก ๊ฐ์ ๋ฆฌํดํ๋ค.map.has(key)
โ key๊ฐ ์์ผ๋ฉด true๋ฅผ ๋ฐํํ๊ณ ๊ทธ๋ ์ง ์์ผ๋ฉด false๋ฅผ ๋ฆฌํดํ๋ค.map.delete(key)
โ key๊ฐ์ ์ญ์ ํ๋ค.map.clear()
โ map์ ๋๋ฉฐ ๋ชจ๋ ์ญ์ ํ๋ค.map.size
โ ์ต๊ทผ ์ฌ์ฉ๋ ์๋ฆฌ๋จผํธ์ ๊ฐฏ์๋ฅผ ๋ฆฌํดํ๋ค.
์๋ฅผ๋ค์ด:
let map = new Map();
map.set('1', 'str1'); // a string key
map.set(1, 'num1'); // a numeric key
map.set(true, 'bool1'); // a boolean key
// remember the regular Object? it would convert keys to string
// Map keeps the type, so these two are different:
alert( map.get(1) ); // 'num1'
alert( map.get('1') ); // 'str1'
alert( map.size ); // 3
๋ณด์๋ค์ํผ, Object์ ๋ฌ๋ฆฌ key๋ ๋ฌธ์์ด๋ก ๋ณํ๋์ง ์๋๋ค. ๋ชจ๋ ์ ํ์ key๊ฐ ๊ฐ๋ฅํฉ๋๋ค.
map์ Object๋ฅผ key๋ก ์ฌ์ฉํ ์๋ ์๋ค.
์๋ฅผ ๋ค์ด:
let john = { name: "John" };
// for every user, let's store their visits count
let visitsCountMap = new Map();
// john is the key for the map
visitsCountMap.set(john, 123);
alert( visitsCountMap.get(john) ); // 123
Object๋ฅผ key๋ก ์ฌ์ฉํ๋ ๊ฒ์ ๊ฐ์ฅ ๋์ ๋๊ณ ์ค์ํ map ๊ธฐ๋ฅ ์ค ํ๋์ด๋ค. ๋ฌธ์์ด ํค์ ๊ฒฝ์ฐ ๊ฐ์ฒด๋ ์ ์์ผ ์ ์์ง๋ง ๊ฐ์ฒด ํค๋ ์ ์์ผ ์ ์๋ค.
let john = { name: "John" };
let visitsCountObj = {}; // try to use an object
visitsCountObj[john] = 123; // try to use john object as the key
// That's what got written!
alert( visitsCountObj["[object Object]"] ); // 123
visitsCountObj
๋ ๊ฐ์ฒด์ด๊ธฐ ๋๋ฌธ์ john
๊ณผ ๊ฐ์ ๋ชจ๋ key
๋ฅผ ๋ฌธ์์ด๋ก ๋ณํํ๋ฏ๋ก ๋ฌธ์์ด ํค "[object Object]
"๋ผ๊ณ ๋
ธ์ถํ๋๋ฐ ์ด alert๊ฐ์ ์ฐ๋ฆฌ๊ฐ ์ํ ๊ฒฐ๊ณผ๊ฐ ์๋๋ค.
๋งต์ด ํค๋ฅผ ๋น๊ตํ๋ ๋ฐฉ๋ฒ
๋๋ฑ์ฑ์ ํ ์คํธํ๊ธฐ ์ํด ๋งต์ SameValueZero ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ๋ค. ์๊ฒฉํ ํ๋ฑ
===
๊ณผ ๋์ผํ์ง๋ง, ์ฐจ์ด์ ์NaN
์ดNaN
๊ณผ ๋๋ฑํ๋ค๊ณ ์ฌ๊ฒจ์ง๋ค๋ ๊ฒ์ด๋ค. ๊ทธ๋์NaN
๋ key๋ก ํ์ฉํ ์ ์๋ค. ์ด ์๊ณ ๋ฆฌ์ฆ์ ๋ณ๊ฒฝํ๊ฑฐ๋ ์ฌ์ฉ์ ์ ์ํ ์ ์๋ค.
Chaining
๋ชจ๋ map.set
์ map ์์ฒด๋ฅผ ๋ฐํํ๋ฏ๋ก, ๋ค์ ํธ์ถ์ "์ฒด์ธ"ํ ์ ์๋ค.
map.set('1', 'str1')
.set(1, 'num1')
.set(true, 'bool1');
Iteration over Map
map์์ ๋ฃจํ๋ฅผ ๋๋ ๋ฐฉ๋ฒ์ 3๊ฐ์ง๊ฐ ์๋ค.
map.keys()
โ key๋ฅผ ๋ฆฌํดํ๋ค.map.values()
โ value๋ฅผ ๋ฆฌํดํ๋ค.map.entries()
โ [key, value] ํญ๋ชฉ์ ๋ํด ํ์ฉ ๊ฐ๋ฅํ ๊ฐ์ ๋ฆฌํดํ๋ค. ์ด ๊ฐ์ ๊ธฐ๋ณธ์ ์ผ๋กfor..of
์์ ์ฌ์ฉ๋๋ค.
์๋ฅผ๋ค์ด:
let recipeMap = new Map([
['cucumber', 500],
['tomatoes', 350],
['onion', 50]
]);
// iterate over keys (vegetables)
for (let vegetable of recipeMap.keys()) {
alert(vegetable); // cucumber, tomatoes, onion
}
// iterate over values (amounts)
for (let amount of recipeMap.values()) {
alert(amount); // 500, 350, 50
}
// iterate over [key, value] entries
for (let entry of recipeMap) { // the same as of recipeMap.entries()
alert(entry); // cucumber,500 (and so on)
}
๋ฐ๋ณต์ ๊ฐ์ด ์ฝ์ ๋ ์์๋๋ก ์งํ๋๋ค. map์ ์ผ๋ฐ Object์ ๋ฌ๋ฆฌ ์ด ์์๋ฅผ ์ ์งํ๋ค.
// runs the function for each (key, value) pair
recipeMap.forEach( (value, key, map) => {
alert(`${key}: ${value}`); // cucumber: 500 etc
});
Object.entries: Map from Object
map์ด ์์ฑ๋๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์ด๊ธฐํ๋ฅผ ์ํด ํค/๊ฐ ์์ผ๋ก ๋ฐฐ์ด(๋๋ ๋ค๋ฅธ ํ์ฉ ๊ฐ๋ฅ)์ ์ ๋ฌํ ์ ์๋ค.
// array of [key, value] pairs
let map = new Map([
['1', 'str1'],
[1, 'num1'],
[true, 'bool1']
]);
alert( map.get('1') ); // str1
์ผ๋ฐ ๊ฐ์ฒด๊ฐ ์๊ณ ์ฌ๊ธฐ์ map์ ์์ฑํ๋ ค๋ฉด ๊ฐ์ฒด์ ํค/๊ฐ ์ ๋ฐฐ์ด์ ํด๋น ํ์์ผ๋ก ์ ํํ๊ฒ ๋ฐํํ๋ ๊ธฐ๋ณธ ์ ๊ณต ๋ฐฉ๋ฒ Object.entries(obj)๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
์ด์ ๊ฐ์ ๊ฐ์ฒด๋ก๋ถํฐ ์ง๋๋ฅผ ๋ง๋ค ์ ์๋ค.
let obj = {
name: "John",
age: 30
};
let map = new Map(Object.entries(obj));
alert( map.get('name') ); // John
์ฌ๊ธฐ์ Object.entries๋ ["name","John", ["age", 30] ๋ฑ์ ํค/๊ฐ ์์ ๋ฐฐ์ด์ ๋ฐํํ๋ค.
Object.fromEntries: Object from Map
Object.entries(obj)
๋ฅผ ์ฌ์ฉํ์ฌ ์ผ๋ฐ ๊ฐ์ฒด์์ map
์ ๋ง๋๋ ๋ฐฉ๋ฒ์ ๋ฐฉ๊ธ ์ดํด๋ณด์๋ค.
Object.fromEntries
๋ [key, value]
์์ ๋ฐฐ์ด์ ์ง์ ํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๋ฐฉ๋ฒ์ผ๋ก ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค.
let prices = Object.fromEntries([
['banana', 1],
['orange', 2],
['meat', 4]
]);
// now prices = { banana: 1, orange: 2, meat: 4 }
alert(prices.orange); // 2
Object.fromEntries
๋ฅผ ์ฌ์ฉํ์ฌ map
์์ ์ผ๋ฐ ๊ฐ์ฒด๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๋ค.
์๋ฅผ ๋ค์ด, ์ฐ๋ฆฌ๋ ๋ฐ์ดํฐ๋ฅผ ์ง๋์ ์ ์ฅํ์ง๋ง, ์ผ๋ฐ ๊ฐ์ฒด๋ฅผ ์์ํ๋ ์ 3์ ์ฝ๋๋ก ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํด์ผ ํ๋ค.
์๋ฅผ๋ค์ด:
let map = new Map();
map.set('banana', 1);
map.set('orange', 2);
map.set('meat', 4);
let obj = Object.fromEntries(map.entries()); // make a plain object (*)
// done!
// obj = { banana: 1, orange: 2, meat: 4 }
alert(obj.orange); // 2
call to map.entries()
๋ Object.fromEntries
์ ๋ํ ์ฌ๋ฐ๋ฅธ ํ์์ผ๋ก ํค/๊ฐ ์์ ๋ฐฐ์ด์ ๋ฐํํ๋ค.
line(*)์ ๋ ์งง๊ฒ ๋ง๋ค ์๋ ์๋ค.
let obj = Object.fromEntries(map); // omit .entries()
๋ง์ฐฌ๊ฐ์ง๋ก Object.fromEntries
๋ ์ธ์๋ก ํ์ฉ ๊ฐ๋ฅํ ๊ฐ์ฒด๋ฅผ ์์ํ๊ธฐ ๋๋ฌธ์ด๋ค. ๋ฐ๋์ ๋ฐฐ์ด์ ์๋๋ค.
๋ํ map
์ ํ์ค ๋ฐ๋ณต์ map.entries()
์ ๋์ผํ ํค/๊ฐ ์์ ๋ฐํํ๋ค. ๊ทธ๋์ ์ง๋์ ๊ฐ์ ํค/๊ฐ์ ๊ฐ์ง ํ๋ฒํ ๋ฌผ์ฒด๋ฅผ ์ป์ ์ ์๋ค.
Set
set
์ ๊ฐ ๊ฐ์ด ํ ๋ฒ๋ง ๋ฐ์ํ ์ ์๋ ํน์ ์ ํ ์ปฌ๋ ์ด๋ค. ์ฐธ๊ณ ๋ก key๊ฐ ์กด์ฌํ์ง ์๋๋ค.
new set(iterable)
โ ์ธํธ๋ฅผ ์์ฑํ๊ณ , ํ์ฉ ๊ฐ๋ฅํ ๊ฐ์ฒด(์ผ๋ฐ์ ์ผ๋ก ๋ฐฐ์ด)๊ฐ ์ ๊ณต๋ ๊ฒฝ์ฐ, ํด๋น ๊ฐ์ฒด์์ ์ธํธ๋ก ๊ฐ์ ๋ณต์ฌํ๋ค.set.add(value)
โ ๊ฐ์ ์ถ๊ฐํ๊ณ set ์์ฒด๋ฅผ ๋ฐํํ๋ค.set.delete(value)
โ ๊ฐ์ ์ญ์ ํ๊ณ , ํธ์ถ ์๊ฐ์ ๊ฐ์ด ์กด์ฌํ๋ฉด true๋ฅผ ๋ฐํํ๊ณ , ๊ทธ๋ ์ง ์์ผ๋ฉด false๋ฅผ ๋ฐํํ๋ค.set.has(value)
โ ๊ฐ์ด set์ ์์ผ๋ฉด true๋ฅผ ๋ฐํํ๊ณ ๊ทธ๋ ์ง ์์ผ๋ฉด false๋ฅผ ๋ฐํํ๋ค.set.clear()
โ ์งํฉ์์ ๋ชจ๋ ๊ฒ์ ์ ๊ฑฐํ๋ค.set.size
โ ์์ ๊ฐ์.
๊ธฐ๋ณธ ๊ธฐ๋ฅ์ ๋์ผํ ๊ฐ์ ๊ฐ์ง set.add(value)
์ ๋ฐ๋ณต ํธ์ถ์ ์๋ฌด ๊ฒ๋ ์ํํ์ง ์๋๋ค๋ ๊ฒ์ด๋ค. ๊ฐ ๊ฐ์ด set์ ํ ๋ฒ๋ง ๋ํ๋๋ ์ด์ ์ด๋ค.
์๋ฅผ ๋ค์ด, ๋ฐฉ๋ฌธ๊ฐ๋ค์ด ์ค๊ณ , ์ฐ๋ฆฌ๋ ๋ชจ๋ ์ฌ๋๋ค์ ๊ธฐ์ตํ๊ธฐ๋ฅผ ์ํ๋ค.
ํ์ง๋ง ๋ฐ๋ณต์ ์ธ ๋ฐฉ๋ฌธ์ด ์ค๋ณต์ผ๋ก ์ด์ด์ง๋ฉด ์ ๋๋ค. ๋ฐฉ๋ฌธ์๋ ํ ๋ฒ๋ง "count"ํด์ผ ํ๋ค.
let set = new Set();
let john = { name: "John" };
let pete = { name: "Pete" };
let mary = { name: "Mary" };
// visits, some users come multiple times
set.add(john);
set.add(pete);
set.add(mary);
set.add(john);
set.add(mary);
// set keeps only unique values
alert( set.size ); // 3
for (let user of set) {
alert(user.name); // John (then Pete and Mary)
}
์งํฉ์ ๋์์ ์ฌ์ฉ์ ๋ฐฐ์ด๊ณผ arr.find
๋ฅผ ์ฌ์ฉํ์ฌ ์ฝ์
ํ ๋๋ง๋ค ์ค๋ณต ํญ๋ชฉ์ ํ์ธํ๋ ์ฝ๋์ผ ์ ์๋ค.
ํ์ง๋ง ์ฑ๋ฅ์ ํจ์ฌ ๋ ๋์ ๊ฒ์ด๋ค. ์ด ๋ฐฉ๋ฒ์ ์ ์ฒด array
๋ฅผ ํตํด ๋ชจ๋ ์์๋ฅผ ๊ฒ์ฌํ๊ธฐ ๋๋ฌธ์ด๋ค. ์ค์ ์ ๊ณ ์ ์ฑ ๊ฒ์ฌ๋ฅผ ์ํด ๋ด๋ถ์ ์ผ๋ก ํจ์ฌ ๋ ์ ์ต์ ํ ๋์ด์๋ค.
Iteration over Set
๋ฃจํ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ for..of
ํน์ forEach
๋ฅผ ์ฌ์ฉํด์ผํ๋ค.
let set = new Set(["oranges", "apples", "bananas"]);
for (let value of set) alert(value);
// the same with forEach:
set.forEach((value, valueAgain, set) => {
alert(value);
});
forEach
์ ์ ๋ฌ๋ ์ฝ๋ฐฑ ํจ์์๋ ๊ฐ, ๊ทธ ๋ค์ ๋์ผํ valueAgain
, ๊ทธ๋ฆฌ๊ณ ๋์ ๊ฐ์ฒด์ ์ธ ๊ฐ์ง ์ธ์๊ฐ ์๋ค. ์ค์ ๋ก ๋์ผํ ๊ฐ์ด ์ธ์์ ๋ ๋ฒ ๋ํ๋๋ค.
์ด๋ callback์ด ์ ๋ฌ๋ Map๊ณผ์ ํธํ์ฑ์ ์ํ ๊ฒ์ด๋ค. ๊ฐ์๋ ์ธ ๊ฐ์ ์ธ์๊ฐ ์๋ค.
๊ทธ๋ฌ๋ ์ด๋ค ๊ฒฝ์ฐ์๋ map์ ์ฝ๊ฒ Set๋ก ๊ต์ฒดํ๊ฑฐ๋ ๊ทธ ๋ฐ๋๋ก ๊ต์ฒดํ๋ ๋ฐ ๋์์ด ๋ ์ ์๋ค.
map์ด ๋ฐ๋ณต๊ธฐ์ ๋ํด ๊ฐ์ง๋ ๊ฒ๊ณผ ๋์ผํ ๋ฐฉ๋ฒ๋ ์ง์๋๋ค.
set.keys()
โ ๊ฐ์ ๋ํด ํ์ฉ ๊ฐ๋ฅํ ๊ฐ์ฒด๋ฅผ ๋ฐํset.values()
โ set.keys()์ ๋์ผํ๋ฉฐ, ์ง๋์์ ํธํ์ฑset.entries()
โ [value, value] ํญ๋ชฉ์ ๋ํด ํ์ฉ ๊ฐ๋ฅํ ๊ฐ์ฒด๋ฅผ ๋ฐํํ์ฌ map๊ณผ ํธํ