개발/Javascript

[JS] 배열 reduce 함수

hayeonn 2022. 9. 27. 21:31
반응형

Array에는 map()이나 filter(), join() 등의 메소드가 있다. 이 기능은 모두 reduce로도 구현이 된다.

또한 initialValue에 배열이나 객체를 주면 전역으로 객체변수를 하나 만드는 효과를 낼 수 있다. 

 

reduce()

배열의 왼쪽부터 콜백 함수를 실행 후 누산한다.

배열.reduce(function(acc, cur, index, arr){ }[, initialValue])

1. 누산기 accumulator (acc)

2. 현재값 (cur)

3. 현재 인덱스 (index)

4. 원본 배열 (arr)

5. initialValue(optional: 사용해도 되고 안해도 됨) : callback의 최초 호출에서 첫 번째 인수에 제공하는 값이며 초기값을 제공하지 않으면 배열의 첫 번째 요소를 사용한다. 빈 배열에서 초기값 없이 reduce()를 호출하면 오류가 발생한다.

 

const numbers = [1, 2, 3, 4];

const result = numbers.reduce((num1, num2) => num1 + num2);
/*
   1, 2 => 3 (배열값 1번째, 2번째부터 시작)
   3, 3 => 6
   6, 4 => 10
*/
console.log(result);  // 10;

//------------------------------------
const result = numbers.reduce((num1, num2) => num1 + num2, 10);
/*
   10, 1 => 11
   11, 2 => 13
   13, 3 => 16
   16, 4 => 20
*/
console.log(result);  // 20;

for문을 사용해서 풀 때보다 더 간단하고 권장하는 방법이다.

map, filter, reduce와 같은 함수는 순차적으로 값을 접근한다는 개념을 가져서 for문을 사용할 때 작성하는 반복문을 작성하지 않고 사용할 수 있다. 

위의 덧셈 말고도 다른 산술 결과도 가능하다.

const nums = [1, 2, 3, 4];

const sumPlus = nums.reduce((num1, num2) => num1 + num2);   //10
const sumMinus = nums.reduce((num1, num2) => num1 - num2);  //-8
const sumMulti = nums.reduce((num1, num2) => num1 * num2);  //24

 

[initvalue값이 없는 경우]

let numbs = [0, 1, 2, 3, 4].reduce(function(acc, cur, idx, arr){
    console.log(`acc : ${acc}`);
    console.log(`cur : ${cur}`);
    console.log(`idx : ${idx}`);
    console.log("            ");
    return acc + cur;
});
//10

initialValue를 제공하지 않으면 reduce()는 인덱스 1부터 시작해서 콜백 함수를 실행하고 첫 번째 인덱스는 건너뛴다.

reduce()함수 호출시 initialValue 값이 없을 때,
- acc : 배열의 첫번째 값
- cur : 배열의 두번째 값
콜백 acc cur idx arr 반환값
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

따라서 마지막 콜백 호출의 반환값인 10을 반환한다.

 

[initValue 값이 있는 경우]

let numbs = [0, 1, 2, 3, 4].reduce(function(acc, cur, idx, arr){
    console.log(`acc : ${acc}`);
    console.log(`cur : ${cur}`);
    console.log(`idx : ${idx}`);
    console.log("            ");
    return acc + cur;
}, 10); //초기값 10을 줌.
//20

initialValue 를 (10) 설정하면 인덱스 0 에서 시작한다.

reduce()함수 호출시 initialValue 값이 있을 때,
- acc : initialValue
- cur : 배열의 첫번째
콜백 acc cur idx arr 반환값
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

따라서 마지막 콜백 호출의 반환값인 20을 반환한다.

 

[객체 배열에서 값 합산]

객체로 이루어진 배열에 들어있는 값을 합산하기 위해 반드시 initialValue 초기값을 줘야한다.

초기값을 줘야 각 항목이 모두 리듀서를 거치게 된다.

const initialValue = 0;
const list = [
    { x : 1 },
    { x : 2 },
    { x : 3 }
];

const listSum = list.reduce((acc, cur) => {
    return acc + cur.x;
}, initialValue);

console.log(listSum); // 6

 

[중첩 배열 펼치기]

const arr = [
    [0, 1],
    [2, 3],
    [4, 5]
];

const flatArr = arr.reduce((acc, cur) => [...acc, ...cur], []);

console.log(flatArr);  // [0, 1, 2, 3, 4, 5]

 

[속성으로 객체 분류하기]

const members = [
    {
        name : 'nana',
        age : 20
    },
    {
        name : 'mimi',
        age : 20
    },
    {
        name : 'sora',
        age : 22
    }
];

function groupBy(objectArr, property){
    return objectArr.reduce((acc, obj) => {
        const key = obj[property];
        if (!acc[key]){
            acc[key] = [];
        }
        acc[key].push(obj);
        return acc;
    }, {});
}

const groupMember = groupBy(members, 'age');
/*
    groupMember is :
    {
        20: [
            { name: 'nana', age: 20 },
            { name: 'mimi', age: 20 },
        ],
        22 : [{ name: 'sora', age: 22 }]
*/

[객체 내의 값 인스턴스 개수 세기]

const names = ['nana', 'mimi', 'sora', 'nana', 'boa'];

const countNames = names.reduce((acc, cur) => {
    if(name in allNames){
       allNames[name]++;
    }
    else {
        allNames[name] = 1;
    }
    return allNames;
}, {});

// countNames is :
// { 'nana': 2, 'mimi': 1, 'sora': 1, 'boa': 1}

 

[배열의 중복 항목 제거]

set 자료형을 이용해 new Set(arr) 하는 것이 더 간단하다.

reduce를 활용하는 방법 정도로 알아두자.

const arr = [1, 2, 1, 2, 3, 5, 6, 5, 3, 4, 4, 4, 4];

const result = arr.sort().reduce((acc, cur) => {
    const length = acc.length;
    if(legnth === 0 || acc[length - 1] !== cur){
        acc.push(cur);
    }
    return acc;
}, []);
console.log(result);  //[1, 2, 3, 4, 5]

 

[filter를 reduce로 구현]

[2, 4, 5, 6, 8].filter(value => value % 2 === 0) // [2, 4, 6, 8]

[2, 4, 5, 6, 8].reduce((acc, cur) => {
    if(value % 2 === 0) acc.push(value);
    return acc;
}, []); 
// [2, 4, 6, 8]

 

[filter + map 조합을 reduce 하나로 구현]

[2, 4, 5, 6, 8]
    .filter(val => val % 2 === 0)
    .map(val => val * 10); 
// [20, 40, 60, 80]

[2, 4, 5, 6, 8].reduce((acc, cur) => {
    if(val % 2 === 0) acc.push(val * 10);
    return acc;
}, []);

 

[2차원 배열 풀기]

[[1, 2], [3, 4]].reduce((acc, cur) => [...acc, ...val], []); //[1, 2, 3, 4]

 

 

[출처]

https://velog.io/@awesomelon/%EB%B0%B0%EC%97%B4%EC%97%90%EC%84%9C-%EC%A4%91%EB%B3%B5%EA%B0%92-%EC%A0%9C%EA%B1%B0%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95JS

https://goddaehee.tistory.com/225

 

[JavaScript (4)] Javascript 제어문(1) - 조건문(if문, switch문)

[JavaScript (4)] Javascript 제어문(1) - 조건문(if문, switch문) 안녕하세요. 갓대희 입니다. 이번 포스팅은 [ 자바스크립트 조건문 ] 입니다. : ) 0. 들어가기 앞서 특정 조건 만족 시(참인 경우) 실행하..

goddaehee.tistory.com

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

 

Array.prototype.reduce() - JavaScript | MDN

reduce()** **메서드는 배열의 각 요소에 대해 주어진 **리듀서**(reducer) 함수를 실행하고, 하나의 결과값을 반환합니다.

developer.mozilla.org

https://inpa.tistory.com/entry/JS-%F0%9F%93%9A-%EB%B0%B0%EC%97%B4-%EA%B3%A0%EC%B0%A8%ED%95%A8%EC%88%98-reduce

 

[JS] 📚 배열 고차함수 🚇 reduce()

[reduce / reduceRight] 자바스크립트 Array.prototype 자바스크립트 배열을 반복해서 콜백 함수를 실행 후 하나의 결과 값을 반환 reduce 는 왼쪽 원소부터 콜백 함수를 실행 reduceRight 는 오른쪽 원소부터 콜

inpa.tistory.com