Javascript - Array reduce, reduceRight 사용법

이번에는 Javascript의 array가 가진 filter 함수의 정의와 사용법 더불어 활용법에 대해 이야기해보려고 합니다. array의 함수 중 map, filter만큼 잘 쓰이는 함수는 아니지만 함수 결과를 체이닝 형식으로 사용하기 때문에 합산과 같은 연속적인 일들의 결과를 만들어 낼 때 자주 사용됩니다.

reduce 정의

Array.prototype.reduce ( callbackfn [ , initialValue ] )

reduce는 단어 의미 그대로 해석하면 줄이다는 표현인데, 함수로 정의된 내용은 배열의 값을 하나씩 줄여가면서 모든 배열을 순회할 때까지 결과를 callbackfn에 전달합니다. 주로 그룹 지어진 데이터의 결과를 도출할 때 사용하는 편입니다. 예를 든다면 덧셈이나 곱셈 같은 합산 식을 이용할 때 사용됩니다. 빅데이터 프레임워크인 맵리듀스(MapReduce)와 같은 이름도 같은 맥락에서 지어진 거라고 생각하시면 더 이해하기 편하실 수 있어요. ECMA에는 "주어진 배열의 값들을 오름차순으로 접근해 callback을 함수로 호출해 결과를 만들어 반환한다"라고 정의되어 있습니다. reduceRight는 reduce와 배열의 값들을 내림차순으로 접근한다는 부분만 다를 뿐 나머지는 동일한 원리로 동작합니다. 예제를 통해 reduce의 정의를 살펴보면 다음과 같습니다. 

const numbers = [1, 2, 3, 4];
const result = numbers.reduce((number1, number2) => number1 + number2);

console.log(result);
// 10;

예제 코드는 주어진 값들을 reduce를 통해 합산하는 방법입니다. 물론 for문을 사용해서도 이와 같은 작업을 할 수는 있지만 권장하지는 않습니다. map, filter, reduce와 같은 함수는 기본적으로 순차적으로 값을 접근한다라는 개념을 가지기 때문에 for문을 사용할 때 작성해야 하는 반복문을 작성하지 않고도 사용할 수 있습니다.

const numbers = [1, 2, 3, 4];
let result = 0;

for (i = 0; i < numbers.length; i++) {
    result += numbers[i];
}

console.log(result);
// 10

reduce 사용법

reduce의 사용 방법은 callbackfn을 통해 주어진 4개의 인자(초기 값, 요소 값, index, 순회하는 대상 객체)를 사용해 결과를 반환하는 함수를 등록하는 것입니다.

const numbers = [1];

const resultWithInitialize = numbers.reduce((accumulator, number, index, source) => {
	
    // accumulator: 누적 값 [옵션을 통해 초기값이 주어지지 않은 경우 배열 인자의 첫번째 값을 사용한다.]
    // number: 요소값
    // index: source에서 요소의 index
    // source: 순회하는 대상
    
    console.log(accumulator);
    // 10
    
    console.log(number);
    // 1

    console.log(index);
    // 0

    console.log(source);
    // [1]

    return accumulator + number;
}, 10);

console.log(resultWithInitialize);
// 11

const result = numbers.reduce((accumulator, number, index, source) => {
	
    // accumulator: 누적 값 [옵션을 통해 초기값이 주어지지 않은 경우 배열 인자의 첫번째 값을 사용한다.]
    // number: 요소값
    // index: source에서 요소의 index
    // source: 순회하는 대상

    console.log(accumulator);
    // 1
    
    console.log(number);
    // 0

    console.log(index);
    // 0

    console.log(source);
    // [1]

    return accumulator + number;
});

console.log(result);
// 1

위에서 제시한 예제 코드 중 초기값을 주지 않은 result의 reduce는 실제로 동작하지 않습니다. 설명을 돕기 위해 작성한 코드입니다. 초기값을 주는 것은 옵션이니 상황에 따라 시작하는 값이 필요하다면 넣고 그럴 필요가 없다면 사용하지 않으시면 됩니다. 초기값을 넣지 않으면 배열의 첫 번째 값을 초기값을 사용하니 이 부분만 인지하면 reduce를 쉽게 사용할 수 있습니다. 위에서는 덧셈만 해보았으니 이번에는 뺄셈과 곱셈도 해보죠

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

const sumByPlus = numbers.reduce((number1, number2) => number1 + number2);
const sumByMinus = numbers.reduce((number1, number2) => number1 - number2);
const sumByMulti = numbers.reduce((number1, number2) => number1 * number2);

console.log(sumByPlus);
// 10;

console.log(sumByMinus);
// -8

console.log(sumByMulti);
// 24

reduce를 사용하는 할 때 주의해야 하는 사항이 있습니다. map, filter 등 배열이 가진 함수들은 같은 주의점이 있으니 알아두시면 좋습니다.

 

- reduce 함수는 객체를 직접 사용하거나 변형시키지 않지만 callbackfn을 통해 수정할 수 있으며 이는 문제를 발생시키는 원인이 됩니다.

- callbackfn이 호출되는 범위는 callbackfn이 처음 호출되기 이전이며, 순회하는 도중에 추가된 요소는 접근하지 않습니다. 반대로 순회하는 도중 수정이 일어나면 변경된 값이 callbackfn에 전달되고 삭제된 요소는 접근하지 않습니다.

// array 요소가 추가되는 경우
const numbers = [1, 2, 3, 4];

const result = numbers.reduce((number1, number2) => {
    numbers.push(number1);
    return number1 + number2;
});

console.log(result);
// 10;

// array 요소가 수정되는 경우
const numbers = [1, 2, 3, 4, 5];

const result = numbers.reduce((number1, number2) => {
    numbers.pop();
    return number1 + number2;
});


console.log(result);
// 6;

 

 

reduce 활용법

- 고차 함수 사용하기

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

const sum = (number1, number2) => number1 + number2;

const result = numbers.reduce(sum);

console.log(result);
// 10

filter는 고차 함수를 사용해서 미리 정의한 식이나 정의되어 있는 식을 사용할 수 있습니다.

- 객체를 기준으로 합산하기

const guys = [
    { name: 'YD', money: 500000 },
    { name: 'Bill', money: 500000 },
    { name: 'Mark', money: 400000 },
    { name: 'Andy', money: 300000 },
    { name: 'Roky', money: 200000 },
    { name: 'Kan', money: 100000 },
    { name: 'Sam', money: 100000 }
];

const sum = (money, person) => money + person.money;

const result = guys.reduce(sum, 0);

console.log(result);
// 2100000

옵션을 통해 초기화 값을 주고 객체가 가진 값을 가져와 더하면 이와 같이 합산을 할 수 도 있습니다.

반응형

댓글

Designed by JB FACTORY