javascript functional programming map filter and reduce - Lee-hyuna/33-js-concepts-kr GitHub Wiki
์๋ฐ์คํฌ๋ฆฝํธ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ โ map, filter ๊ทธ๋ฆฌ๊ณ reduce
์๋ฌธ: JavaScript Functional Programming โ map, filter and reduce
์ฌ๋ฌ๋ถ์ด ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ด ๋ฌด์์ธ์ง ๋ชจ๋ฅด๋๋ผ๋, ์๋ง๋ map, filter, ๊ทธ๋ฆฌ๊ณ reduce๋ฅผ ์ฌ์ฉํด ๋ดค์ ๊ฒ์ด๋ค. ์ด๊ฒ๋ค์ ๋งค์ฐ ์ ์ฉํ๊ณ ๋ ๊นจ๋ํ ๋ก์ง์ ์์ฑํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
์ด ๊ธฐ์ฌ์ ์ ๋ชฉ์ '์๋ฐ์คํฌ๋ฆฝํธ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ'์ด์ง๋ง, ๊ทธ ์ฃผ์ ์ ๋๋ฌด ๊น์ด ๋น ์ ธ๋ค์ง ์์ ๊ฒ์ด๋ค. ์ฐ๋ฆฌ๋ map, filter ๊ทธ๋ฆฌ๊ณ reduce๋ฅผ ์ดํด ๋ณผ ๊ฒ์ด๋ค. ์ด๊ฒ์ ๊ธฐ๋ณธ์ ์ผ๋ก ํจ์ํ์ด๋ผ ๋ถ๋ฆฌ๋ ์ฝ๋ฉ์ ์ ๋ง ๋ฉ์ง ์ธ๊ณ์ ๋ํ ์ธ์์ ๋์ด๊ธฐ ์ํ ๋ง์ผํ ์๋ฒ์ด๋ค. ์๋ง ๋ค์ด๋ณธ ์ ๋ ์์ ๊ฒ์ด๊ณ , ๋ค์ ์ ๋ ์์ ๊ฒ์ด์ง๋ง, ์๊ฐํด ๋ณธ ์ ๋ ์์ ๊ฒ์ด๋ค.
ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ๋ํ ์์ธํ ๋ด์ฉ์ Frisby ๊ต์์ ๊ฐ์ฅ ์ ์ ํ ๊ธฐ๋ฅ ํ๋ก๊ทธ๋๋ฐ ๊ฐ์ด๋๋ฅผ ์ฐธ์กฐํ๋ผ. (Link) ๋๋ Functional-Light JavaScript by the awesome Kyle Simpson (Link) ๋๋ ์ ์ค์ธ ๋จ์, ์๋ฆญ ์๋ฆฌ์์ ๊ธ์ ๋ณด๋ผ. ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ๋ํด ์์ฃผ ์ด์ผ๊ธฐํ๋ค.
์ด ๊ฐ๋ ๋ค ์ค ์ผ๋ถ๊ฐ ์ฒ์ ์ ํ์ ๋ ์ดํด๊ฐ๋์ง ์๋๋ค๊ณ ํด๋, ๊ฑฑ์ ํ์ง ๋ง์๋ผ. ๊ทธ๊ฒ์ ๋น์ฐํ ๊ฒ์ด๋ค. ๊ณ์ํ๋ฉด ๊ณง ๊ทธ ๋ณด์์ ์ป๊ฒ ๋ ๊ฒ์ด๋ค. ๋ด ์๊ฐ์ ์ฌ๊ธฐ์ ๊ฐ์ฅ ์ค์ํ ๊ฒ์ ๋น์ ์ด ๋ ๋์ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๋ฅผ ์ฐ๋ ๋ฐ ๋์์ด ๋ ์๋ก์ด ์ ๊ทผ๋ฒ์ ์๊ฐํ๋ ๊ฒ์ด๋ค.
map
MDN์ด ๋งํ๋ 'map'์ด ๋ฌด์์ธ์ง ์ดํด๋ณด์ (Link):
์ค๋ช
map()
๋ฉ์๋๋ ๋ฐฐ์ด์ ๋ชจ๋ ์์์ ์ ๊ณต๋ ํจ์๋ฅผ ์ ์ฉํ์ฌ, ๊ฒฐ๊ณผ๋ก ์ ๋ฐฐ์ด์ ์์ฑํ๋ค.
์์
const numbers = [2, 4, 8, 10];
const halves = numbers.map(x => x / 2);// halves is [1, 2, 4, 5]
ํน๋ณํ ๊ฒ์ด ์๋ค. ๋จ์ง numbers ๋ฐฐ์ด์ ๊ฐ์ ๊ฒํ ํ์ฌ, ์ ๋ฐ์ผ๋ก ๋๋๊ณ ๊ทธ ๊ฒฐ๊ณผ๋ก ์๋ก์ด ๋ฐฐ์ด (halves)์ ๋ง๋ค์๋ค.
map
์ ๋ฐฐ์ด์ด ์กด์ฌํ๊ณ , ๊ทธ ๋ฐฐ์ด์ ๋ชจ๋ ํญ๋ชฉ์ ๋ํด ๋ฌด์ธ๊ฐ๋ฅผ ํ๊ณ ์ถ์ ๋ ์ฌ์ฉ๋๋ค.
filter
MDN์ด ๋งํ๋ 'filter'๊ฐ ๋ฌด์์ธ์ง ์ดํด๋ณด์ (Link):
์ค๋ช
filter()
๋ฉ์๋๋ ๋ฐฐ์ด์ ๋ชจ๋ ์์์ ์ ๊ณต๋ ํจ์์ ์กฐ๊ฑด์ ๋ง์กฑํ๋์ง ํ๋จํ์ฌ, ๊ฒฐ๊ณผ๋ก ์ ๋ฐฐ์ด์ ์์ฑํ๋ค.
์์
const words = ["spray", "limit", "elite", "exuberant", "destruction", "present"];
const longWords = words.filter(word => word.length > 6);// longWords is ["exuberant", "destruction", "present"]
map
๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก filter
์ญ์ ํน๋ณํ ๊ฒ ์๋ค. words ๋ฐฐ์ด์์ ์ด๋ค ๊ฐ์ด ์กฐ๊ฑด์ ๋ง๋์ง ํ์ธํ์ฌ (๊ธธ์ด๊ฐ 6 ์ด์), ํด๋น ๊ฐ๋ค์ ์ ๋ฐฐ์ด์ ๋ด์ ๋ฐํํ๋ค.
reduce
reduce๋ ๋ค์ฌ๋ค๋ฅํ๊ณ ์ ์ฐํ๋ค. ์ ๋ง์ ์๋๋ฆฌ์ค์ ์ฌ์ฉ๋ ์ ์๋ค. ๊ทธ๋ฌ๋ ๋์ฒด๋ก ์ซ์ ๋ฐฐ์ด์ ํฉ์ ๊ตฌํ๊ฑฐ๋ ํน์ ์์ฑ์ ํฉ๊ณ๋ฅผ ๊ตฌํ๋ ๊ฒ์ ์ฌ์ฉ๋๋๋ฐ, ์ํ๊น์ด ์ผ์ด๋ค.
MDN์ด ๋งํ๋ 'reduce'๊ฐ ๋ฌด์์ธ์ง ์ดํด๋ณด์ (Link):
์ค๋ช
reduce()
๋ฉ์๋๋ ๋ฐฐ์ด์ ๊ฐ ์์(์ผ์ชฝ์์ ์ค๋ฅธ์ชฝ์ผ๋ก)์ ๋ํด ๋์ฐ๊ธฐ(accumulator)์ ํจ๊ป ํจ์๋ฅผ ์ ์ฉํ์ฌ ๋จ์ผ ๊ฐ์ผ๋ก ๊ฐ์์ํจ๋ค.
์์
const total = [0, 1, 2, 3].reduce((acc, value) => acc + value, 1);// total is 7
๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ์์๋ ํฉ์ ๊ตฌํ๋ ๊ฒ์ด๋ค. ๊ทธ๋ฌ๋ ๊ฐ๋ฐ์๋ค๋ก ๋ถํฐ ์์์ฐจ๋ฆฐ ๊ฒ์ ์ด๋ค ์ซ์๋ค์ ํฉํ ์ผ์ด ๋ณ๋ก ์๋ค๋ ๊ฒ์ด๋ค. ๊ทธ๋์ reduce
๊ฐ ์กด์ฌํ๋ค๋ ๊ฒ์ ์๊ฑฐ๋ ํน์ ์ด๋ค ์ซ์๋ค์ ํฉํด์ผ ํ ๋์๋ง ์กด์ฌํ๋ค๋ ๊ฒ์ ๊ธฐ์ตํ์ง๋ง (์์์ ์์ํ๋ ๊ฒ์ฒ๋ผ) reduce
๋ ๋จ์ํ ํฉํ ๊ฒ ์ด์์ ๊ฒ์ ํ ์ ์๋ค.
reduce
์ ์ ๋ง ๋ฉ์ง ์ ์ ์ฝ๋ฐฑ ํจ์์ ํธ์ถ์ ๊ฒฐ๊ณผ๋ฅผ ๋ค์ ์ฝ๋ฐฑ ํจ์์ ํธ์ถ๋ก ์ ๋ฌํ์ฌ ์์์ ๊ฐ์ด ๋์ํ ์ ์๊ฒ ํ๋ค.
Compose Functions (ํจ์์ ํฉ์ฑ)
reduce
๋ฅผ ์ด์ฉํ์ฌ ํจ์๋ฅผ ํฉ์ฑํ๋ ์์ ๋ Eric Elliott์ด ์ด reduce ๊ธ์์ ๋ฐ์ทํ์๋ค. Eric Elliott์ ํญ์ ์์ง์ ์ปจํ ์ธ ๋ฅผ ์์ฐํ๊ณ ๊ฐ๋ฅํ ๋ชจ๋ ํ๋ซํผ์์ ๊ทธ๋ฅผ ๋ฐ๋์ผ๋ฉด ์ข๊ฒ ๋ค. Link
์ฐ๋ฆฌ์๊ฒ ๊ฐ์ฅ ํฅ๋ฏธ๋ก์ด ๋ถ๋ถ์ ๋ค์๊ณผ ๊ฐ๋ค.
const compose = (...fns) => x => fns.reduceRight((v, f) => f(v), x);
/*
const compose = (...fns) => {
return (x) => {
return fns.reduceRight((v, f) => f(v), x)
}
};
*/
๋ง์น ์ ์ฒ๋ผ ๋ณด์ด์ง ์๋๊ฐ?
compose๋ ์ปค๋ง ํจํด ํํ๋ก์จ ๋ถ๋ถ์ ์ผ๋ก ์ ์ฉ๋๋ฉฐ, ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ค์ ํจ์๋ก ์ ๋ฌํ๋ค. rest parameters ๊ฐ ์ฌ์ฉ๋ ๊ฒ์ ์ฃผ๋ชฉํ๋ผ. ๋๋ฌธ์ ์ํ๋ ๋งํผ์ ํจ์๋ฅผ ์ ๋ฌ ํ์ฌ fns ๋ฐฐ์ด์ ๋ฃ์ ์ ์๋ ๊ฒ์ด๋ค.
๊ทธ๋ฐ compose์ ํจ์๋ค์ ์ ๋ฌํ ๋ค์ ์ด๊ธฐ ๊ฐ (x)๋ฅผ ์ ๋ ฅํ๋ฉด ๋๋ค.
์์ง๋ ํจ์์ ๋ฐฐ์ด(fns)์ x๋ฅผ ์ด๊ธฐ๊ฐ์ผ๋ก ์ ๋ฌํ์ฌ reduceRight๋ฅผ ํธ์ถํ์ฌ ๋ฐํํ๋ค.
reduceRight๋ reduce์ ๊ธฐ๋ฅ์ ๊ฐ์ง๋ง ๋ฐฐ์ด์ ๋์์ ์์ํ์ฌ ์์์ ์ผ๋ก ์ด๋ํ๋ค.
์ฌ์ฉ ์:
const add1 = n => n + 1;
const double = n => n * 2;const add1ThenDouble = compose(
double,
add1
);add1ThenDouble(2); // 6
// ((2 + 1 = 3) * 2 = 6)
ํ๋ฅญํ๋ค!
ํ๋ก๋ฏธ์ค ์ฒด์ด๋
reduce๋ฅผ ์ด์ฉํ ํ๋ก๋ฏธ์ค ์ฒด์ธ ์์ ๋ Bobby Brennan์ ํ๋ก๋ฏธ์ค ํจํด๊ณผ ์ํฐ-ํจํด์ ๊ดํ ํ๋ฅญํ ๊ธ์์ ๋ฐ๊ฒฌํ๋ค.
์ฌ๋ฏธ์๋ ๋ถ๋ถ :
let itemIDs = [1, 2, 3, 4, 5];
itemIDs.reduce((promise, itemID) => {
return promise.then(_ => api.deleteItem(itemID));
}, Promise.resolve());
์ ์ฝ๋๋ ์๋์ ๊ฐ์ด ํด์๋๋ค :
Promise.resolve()
.then(_ => api.deleteItem(1))
.then(_ => api.deleteItem(2))
.then(_ => api.deleteItem(3))
.then(_ => api.deleteItem(4))
.then(_ => api.deleteItem(5));
์ด ์์ ๋ ๋ณต์กํ์ง๋ ์๊ณ ๊ฐ๋จํ๋ค. reduce๋ฅผ ํ๋ฉด ์ฝ๋๊ฐ ์์ฒญ ๊ฐ๊ฒฐํด์ง๋ค. 40๊ฐ ์ด์์ ID๋ฅผ ๊ฐ์ง ๋ฐฐ์ด์ด ์๊ณ reduce๋ฅผ ์ฌ์ฉํ์ง ์๋๋ค๊ณ ์์ํด๋ณด๋ผ.
๊ฒฐ๋ก
map, filter, reduce๋ฅผ ์ ๋ง ๋ฉ์ง๊ณ ์ฐฝ์์ ์ธ ๋ฐฉ๋ฒ์ผ๋ก ์ฌ์ฉํ๋ ๊ฑธ ๋ดค๋ค. ๋ฉ์ง๊ณ ์ฐฝ์์ ์ธ ์๋ค์ reduce๋ฅผ ์ํ ๊ฒ์ด์์ ๋ฟ์ด์ง๋ง.. ๋ง์ฝ map, filter, reduce๊ฐ ์ฌ์ฉ๋ ํฅ๋ฏธ๋ก์ด ๋ฐฉ๋ฒ๋ค์ ๋ฐ๊ฒฌํ๋ฉด ๊ณต์ ํด ์ฃผ๊ธธ ๋ฐ๋๋ค. ์ด 3๊ฐ์ง๋ฅผ ์ฌ์ฉํ ์ ์๋ ์ค์ฉ์ ์ธ ๋ฐฉ๋ฒ๋ค์ด ๋ง์ด ์๋ค๊ณ ํ์ ํ๋ค!