일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 스프링 클라우드
- gitlab
- STS
- map
- 자바
- 도커
- 코딩테스트
- spring security
- docker
- Java
- 스프링부트
- date
- GIT
- 스프링
- OAuth
- JS
- 유레카
- IntelliJ
- Spring Cloud
- 자바스크립트
- spring boot
- JavaScript
- SpringBoot
- 비동기
- leetcode
- map()
- Spring
- EUREKA
- 프로그래머스
- jQuery
- Today
- Total
RATSENO
[JS]map(), reduce() 함수 본문
자바스크립트의 내장 메서드 중에서 가장 강력하고 유용하다고 알려진 map(), reduce() 함수에 대해서 알아보겠습니다.
개발을 하다보면 배열을 다뤄야하는 경우가 굉장히 많습니다. 최근에 filter()메서드를 유용하게 잘 써먹게되면서, 다른 메서드들에 대해서도 알아봐야겠다는 생각이 들었습니다. (ㅠㅠ 반복문으로 해결하려던 과거의 저를 되돌아보게됬습니다.)
함께 map(), reduce() 함수를 알아보도록 하겠습니다.!
map() 메서드
arr.map(callback(currentValue[, index[, array]])[, thisArg])
매개변수
callback : 새로운 배열 요소를 생성하는 함수. 다음 세 가지 인수를 가집니다.
-currentValue : 처리할 현재 요소
-index(optional : 사용해도 되고 안해도 되고) : 처리할 현재 요소의 인덱스
-array(optional : 사용해도 되고 안해도 되고) : map()을 호출한 배열
-thisArg(optional : 사용해도 되고 안해도 되고) : callback을 실행할 때this로 사용되는 값
반환값
배열의 각 요소에 대해 실행한 callback의 결과를 모은 새로운 배열.
map() 메서드는 배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출한 결과를 모아 새로운 배열을 반환합니다.
간단한 예로 주어진 배열의 요소들을 곱하기 2 하여 반환하는 예제를 들어보겠습니다.
const array = [1, 4, 9, 16];
const map = array.map(function(currentValue, /* index, array */){
return currentValue*2;
});
//ES6의 화살표 함수로 표기하게 되면
//const map = array.map(currentValue => currentValue*2);
console.log(array);
//[1, 4, 9, 16]
console.log(map);
//[2, 8, 18, 32]
map은 callback 함수를 각각의 요소에 대해 한번씩 순서대로 불러 그 함수의 반환값으로 새로운 배열을 만듭니다.
map은 호출한 배열의 값을 변형하지 않습니다. 단, callback 함수에 의해서 변형될 수는 있습니다.
ex) map을 활용해 배열 속 객체를 재구성하기
var kvArray = [{key:1, value:10},
{key:2, value:20},
{key:3, value: 30}];
var reformattedArray = kvArray.map(function(obj){
var rObj = {};
rObj[obj.key] = obj.value;
return rObj;
});
// reformattedArray
//[{1:10}, {2:20}, {3:30}]
// kvArray
// [{key:1, value:10},
// {key:2, value:20},
// {key:3, value: 30}]
ex) map을 포괄적으로 사용하기
var map = Array.prototype.map;
var a = map.call('Hello World', function(x) {
//charCodeAt은 주어진 index에 해당하는 유니코드 값을 리턴하는데
//이 값은 unicode가 지원되는 모든 시스템에서 동일한 문자를 가르킨다.
return x.charCodeAt(0);
});
//[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]
ex) map을 포괄적으로 사용하기 (querySelectorAll)
아래 예제는 querySelectorAll을 사용해서 수집된 객체들을 순회 처리하는 법을 보여줍니다. 이번 경우 체크한 옵션 박스를 콘솔에 프린트합니다.
var elems = document.querySelectorAll('select option:checked');
var values = [].map.call(elems, function(obj) {
return obj.value;
});
reduce() 메서드
reduce() 메서드는 배열의 각 요소에 대해 주어진 리듀서(reducer) 함수를 실행하고, 하나의 결과값을 반환합니다.
map이 배열의 각 요소를 변형한다면 reduce는 배열 자체를 변형합니다. reduce라는 이름은 이 메서드가 보통 배열을 값 하나로 줄이는 쓰이기 때문에 붙었습니다. 예를 들어 배열에 들어있는 숫자를 더하거나 평균을 구하는 것은 배열을 값 하나로 줄이는 동작입니다. 하지만 reduce가 반환하는 값 하나는 객체일 수도 있고, 다른 배열일 수도 있습니다.
리듀서 함수는 네 개의 인자를 가집니다.
- 누산기accumulator (acc)
- 현재 값 (cur)
- 현재 인덱스 (idx)
- 원본 배열 (src)
리듀서 함수의 반환 값은 누산기에 할당되고, 누산기는 순회 중 유지되므로 결국 최종 결과는 하나의 값이 됩니다.
arr.reduce(callback[, initialValue])
매개변수
callback : 배열의 각 요소에 대해 실행할 함수. 다음 네 가지 인수를 받습니다
-accumulator : 누산기accmulator는 콜백의 반환값을 누적합니다. 콜백의 이전 반환값 또는, 콜백의 첫 번째 호출이면서 initialValue를 제공한 경우에는initialValue의 값입니다.
-currentValue : 처리할 현재 요소.
-currentIndex(optional : 사용해도 되고 안해도 되고) : 처리할 현재 요소의 인덱스. initialValue를 제공한
경우 0, 아니면 1부터 시작합니다.
-array(optional : 사용해도 되고 안해도 되고) : reduce()를 호출한 배열.
initialValue(optional : 사용해도 되고 안해도 되고) : callback의 최초 호출에서 첫 번째 인수에 제공하는 값. 초기값을 제공하지 않으면 배열의 첫 번째 요소를 사용합니다. 빈 배열에서 초기값 없이 reduce()를 호출하면 오류가 발생합니다.
반환값
누적 계산의 결과 값.
ex) reduce() 작동 방식 - initValue값이 없는 경우
var res = [0, 1, 2, 3, 4].reduce(function(accumulator, currentValue, currentIndex, array){
console.log(`currentIndex : ${currentIndex}`);
console.log(`accumulator : ${accumulator}`);
console.log(`currentValue : ${currentValue}`);
console.log(`currentIndex : ${currentIndex}`);
console.log(" ");
return accumulator + currentValue;
}, 0);
console.log("res:", res);
//initialValue를 제공하지 않으면, reduce()는 인덱스 1부터 시작해 콜백 함수를 실행하고 첫 번째 인덱스는 건너 뜁니다.
//reduce()함수 호출시 initialValue 값이 없는 경우
//-accumulator 는 배열의 첫번째 값
//-currentValue 는 배열의 두번째 값
콜백은 4번 호출됩니다. 각 호출의 인수와 반환값은 다음과 같습니다.
callback | accumulator | currentValue | currentIndex | array | 반환 값 |
1번째 호출 | 0 | 1 | 1 | [0, 1, 2, 3, 4] | 1 |
2번째 호출 | 1 | 2 | 2 | [0, 1, 2, 3, 4] | 3 |
3번째 호출 | 3 | 3 | 3 | [0, 1, 2, 3, 4] | 6 |
4번째 호출 | 6 | 4 | 4 | [0, 1, 2, 3, 4] | 10 |
reduce()가 반환하는 값으로는 마지막 콜백 호출의 반환값(10)을 사용합니다
ex) reduce() 작동 방식 - initValue값이 없는 경우
var res = [0, 1, 2, 3, 4].reduce(function(accumulator, currentValue, currentIndex, array){
console.log(`currentIndex : ${currentIndex}`);
console.log(`accumulator : ${accumulator}`);
console.log(`currentValue : ${currentValue}`);
console.log(`currentIndex : ${currentIndex}`);
console.log(" ");
return accumulator + currentValue;
}, 10);
console.log("res:", res);
//initialValue를 제공하면 인덱스 0에서 시작합니다.
//reduce()함수 호출시 initialValue 값이 있는 경우
//-accumulator 는 initialValue
//-currentValue 는 배열의 첫번째 값
callback | accumulator | currentValue | currentIndex | array | 반환 값 |
1번째 호출 | 10 | 0 | 0 | [0, 1, 2, 3, 4] | 10 |
2번째 호출 | 10 | 1 | 1 | [0, 1, 2, 3, 4] | 11 |
3번째 호출 | 11 | 2 | 2 | [0, 1, 2, 3, 4] | 13 |
4번째 호출 | 13 | 3 | 3 | [0, 1, 2, 3, 4] | 16 |
5번째 호출 | 16 | 4 | 4 | [0, 1, 2, 3, 4] | 20 |
이 때 reduce()가 결과로 반환하는 값은 20입니다.
ex) 객체 배열에서의 값 합산
객체로 이루어진 배열에 들어 있는 값을 합산하기 위해서는 반드시 초기값을 주어 각 항목이 여러분의 함수를 거치도록 해야 합니다.
var initialValue = 0;
var list = [
{
x : 1
},
{
x : 2
},
{
x : 3
}
];
var sum = list.reduce(function (accumulator, currentValue) {
console.log(`accumulator : ${accumulator}`);
console.log(`currentValue : ${currentValue.x}`);
console.log(" ");
return accumulator + currentValue.x;
}, initialValue)
console.log(sum) // logs 6
ex) 중첩 배열 펼치기
var arr = [
[0, 1],
[2, 3],
[4, 5]
]
var flattened = arr.reduce(function(accumulator, currentValue) {
console.log(`accumulator : ${accumulator}`);
console.log(`currentValue : ${currentValue}`);
return accumulator.concat(currentValue);
}
,[]);
console.log(flattened);
//[0, 1, 2, 3, 4, 5]
ex) 속성으로 객체 분류하기
var peoples = [
{
name : 'Alice',
age : 21
},
{
name : 'Max',
age : 20
},
{
name : 'Jane',
age : 20
}
];
function groupBy(objectArray, property){
return objectArray.reduce(function (accumulator, currentObj) {
var key = currentObj[property];
console.log(`key : ${key}`);
if (!accumulator[key]) {
accumulator[key] = [];
}
accumulator[key].push(currentObj);
return accumulator;
}, {});
};
var groupedPeople = groupBy(peoples, 'age');
console.log(`groupedPeople : ${JSON.stringify(groupedPeople)}`);
//"age" 속성으로 객체 분류 (나이 별)
ex) 배열의 중복 항목 제거
let arr = [1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4];
let result = arr.sort().reduce((accumulator, currentValue) => {
console.log(`accumulator : ${accumulator}`);
console.log(`currentValue : ${currentValue}`);
console.log(` `);
const length = accumulator.length
if (length === 0 || accumulator[length - 1] !== currentValue) {
accumulator.push(currentValue);
}
return accumulator;
}, []);
console.log(result);
//[1,2,3,4,5]
ex) 프로미스를 순차적으로 실행하기
프로미스란?
이전 포스팅 : [JS]Promise (프라미스) - 1
function runPromiseInSequence(arr, input){
return arr.reduce(function(accumulator, currentFunction){
console.log(`accumulator : ${accumulator}`);
console.log(`currentFunction : ${currentFunction}`);
console.log(` `);
return accumulator.then(currentFunction);
}, Promise.resolve(input));
};
function promise1(value){
return new Promise(function(resolve, reject){
console.log(`promise1 -value : ${value}`)
resolve(value * 5);
});
};
function promise2(value){
return new Promise(function(resolve, reject){
console.log(`promise2 -value : ${value}`)
resolve(value * 2);
});
};
function function3(value){
return value * 3;
};
function promise4(value){
return new Promise(function(resolve, reject){
console.log(`promise4 -value : ${value}`)
resolve(value * 4);
});
};
const promiseArr = [promise1, promise2, function3, promise4, ]
runPromiseInSequence(promiseArr, 10)
.then(function(value){
console.log(`result value : ${value}`);
});
'DEV > JS' 카테고리의 다른 글
[JS]맵(Map)과 셋(Set) -2 (0) | 2019.12.04 |
---|---|
[JS]맵(Map)과 셋(Set) -1 (0) | 2019.12.04 |
[JS]Promise (프라미스) - 2 (0) | 2019.11.21 |
[JS]Promise (프라미스) - 1 (0) | 2019.11.20 |
[JS]Ajax (0) | 2019.11.19 |