arr.reduce(callback[, initialValue])
var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
var countedNames = names.reduce(function (allNames, name) {
if (name in allNames) {
allNames[name]++;
}
else {
allNames[name] = 1;
}
return allNames;
}, {});
// countedNames is:
// { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }
배열에 있는 이름이 몇 번 나오는지 세는 문제이다. reduce 메소드의 초기값에 빈 객체 {} 할당하였다. acc 최신 결과값은 allNames 객체다. 키 유무에 따른 조건문으로 처리하였다.
var people = [
{ name: 'Alice', age: 21 },
{ name: 'Bob', age: 33 },
{ name: 'Jane', age: 26 },
{ name: 'Steve', age: 33 },
{ name: 'Joseph', age: 80 }
];
function groupBy(objectArray, property) {
return objectArray.reduce(function (acc, obj) {
var key = obj[property];
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(obj);
return acc;
}, {});
}
var groupedPeople = groupBy(people, 'age');
// groupedPeople is:
// {
// 21: [
// { name: 'Alice', age: 21 },
// ],
// 33: [{ name: 'Bob', age: 33 },
// { name: 'Steve', age: 33 },
// ]
// ...
// }
배열 내 객체는 이름과 나이 속성을 갖는다. 특정 속성으로 그룹 짓고자 할 때 쓰는 함수를 만드는 문제에서 reduce 메소드를 썼다. 역시 초기값으로 빈 객체를 할당해준 뒤 key 유무에 따라 배열 내 요소(객체)를 최신 결과값 객체에 추가한다.
var friends = [{
name: 'Anna',
books: ['Bible', 'Harry Potter'],
age: 21
}, {
name: 'Bob',
books: ['War and peace', 'Romeo and Juliet'],
age: 26
}, {
name: 'Alice',
books: ['The Lord of the Rings', 'The Shining'],
age: 18
}];
var allbooks = friends.reduce(function(accumulator, currentValue) {
return [...accumulator, ...currentValue.books];
}, []);
위 배열의 'books' 속성값을 담은 배열을 출력하는 문제였다. reduce 메소드에 사용된 callback 함수는 .concat 메소드 대신 spread syntax(전개 구문)를 사용하였다.
역시나 초기값은 빈 배열이며, 입력하지 않으면 아래와 같이 뜬다.
accumulator is not iterable. 누산기가 반복 가능하지 않다. 초기값을 설정하지 않으면 배열의 첫번째 요소가 처음 acc(최신 결과값)가 되므로
{
name: 'Anna',
books: ['Bible', 'Harry Potter'],
age: 21
}
해당 객체가 첫번째 acc가 되어 callback 함수의 전개 구문이 동작하지 않는다. 따라서 출력하고자 하는 값이 배열이라면 초기값으로 배열을 넣어줘야한다. <연금술사>를 초기값으로 설정하면 결과에 잘 반영된다.
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce