배열 안의 요소를 순회하면서 하나의 값으로 만들어주는 reduce 함수. map, filter와 함께 많이 쓰이는 메서드라서 연습하는데 헷갈리고 어렵다. 。° ૮₍°´ᯅ`°₎ა °。
나중에 헷갈릴 때 다시 보려고 예제 몇 가지를 수도코드와 함께 정리해본다.
- 결과 값: {26: 2, 75: 1, 50: 1}
const users = [
{ firstName: "akshay", lastName: "saini", age: 26 },
{ firstName: "donald", lastName: "trump", age: 75 },
{ firstName: "elon", lastName: "musk", age: 50 },
{ firstName: "deepika", lastName: "padukone", age: 26 },
];
reduce를 이용해 배열 안의 객체를 순회하면서 같은 나이가 있으면 1씩 추가를 해주는 방법으로 코드를 짠다.
const result = users.reduce((prev, cur) => {}, {})
prev
는 현재값 이전까지의 누적값이고 cur
는 순회하는 현재 값이다.
그 외에 인자로 index
(현재의 인덱스), array
(원본 배열)을 추가할 수 있다.
(이 예제에서는 인덱스와 배열을 불러올 필요가 없으니 누적값과 현재 값만 다룬다.)
화살표 옆에 2개의 중괄호가 보이는데, 두 번째 중괄호는 초깃값이다.
초깃값을 빈 객체({}
)로 지정해서 빈 객체 안에 값을 추가해줄 것이다.
reduce의 두 인자(prev, cur)가 순회할 때마다 값을 어떻게 할당하는지 궁금하다면
console.log()를 찍어보면 된다.
const age_sum = users.reduce((prev, cur) => {
console.log(prev, cur);
}, {});
// console.log 결과
{} { firstName: 'akshay', lastName: 'saini', age: 26 }
undefined { firstName: 'donald', lastName: 'trump', age: 75 }
undefined { firstName: 'elon', lastName: 'musk', age: 50 }
undefined { firstName: 'deepika', lastName: 'padukone', age: 26 }
undefined
두 번째 인덱스부터 prev가 undefined인 이유는 아직 return 값을 지정하지 않았기 때문이다.
const age_sum = users.reduce((prev, cur) => {
console.log(prev, cur);
return prev
}, {});
// console.log 결과
{} { firstName: 'akshay', lastName: 'saini', age: 26 }
{} { firstName: 'donald', lastName: 'trump', age: 75 }
{} { firstName: 'elon', lastName: 'musk', age: 50 }
{} { firstName: 'deepika', lastName: 'padukone', age: 26 }
{}
return 값으로 prev를 지정하면 빈 배열이 나온다.
아직 누적값을 어떻게 처리해줄지 console.log()와 return 사이에 정하지 않았기 때문이다.
그럼 최종적으로 우리가 반환할 값은 prev이므로,
prev 안에는 {나이1: 나이1를 가진 사람의 수, 나이2: 나이2를 가진 사람의 수...}와 같은 형태로 데이터가 누적되어야 한다.
먼저 초깃값(빈 배열)부터 시작한다. 가장 처음의 초깃값은 prev와 같다.
여기에 각 객체의 나이를 담아야 한다.
현재 객체의 나이는 cur.age로 구할 수 있다.
이걸 식으로 표현하면 prev[cur.age]가 된다.
여기서부터 진도를 어떻게 나가야 할지 발상이 어려울 수 있는데,
reduce 함수에서는 초깃값(누적값, 즉 이전값)과 현재값을 비교할 수 있음을 떠올린다.
이 논리를 식으로 표현하면 이렇다.
const age_sum = users.reduce((prev, cur) => {
console.log(prev, cur);
if (prev[cur.age]) {
prev[cur.age] += prev[cur.age];
} else {
prev[cur.age] = 1;
}
return prev;
}, {});
객체의 실제 데이터에 대입해서 설명해본다면
첫 번째 라운드에서 age는 26이다. 이전까지 누적된 값에 26이 있는지 확인한다.
초깃값이 빈 배열이므로 없다. 값에 1을 할당한다.
{ 26: 1 }
두 번째 라운드에서 agr가 75다. 이전까지 누적된 값에 75가 있는지 확인한다.
age는 26인 객체만 있으므로 값에 1을 할당한다.
{ 26: 1, 75: 1 }
이런 식으로 추가해나간다. 마지막 age는 26이므로 26의 값에 하나 더 증가한다.
{26: 2, 75: 1, 50: 1}
최종 결과 값이 잘 반환된다.