Array.prototype.reduce

김명성·2022년 1월 24일
0

자바스크립트

목록 보기
24/26

reduce


문법

Array.reduce(cbfunction(accumulator,currentItemInArray,index)
	//write function context;
,initialValue);

Array.reduce((누적값, 현재값, 인덱스, 요소) => {
  return 결과;
}, 초기값);
//초기값을 설정하지 않으면 0번째 인덱스의 값이 초기값이 된다.

reduce 1.

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

const sum = arrayItems.reduce(function (acc, cur, idx) {
  accumulator = accumulator + currentItemInArray;
  return accumulator;
}, 0);

// sum = 21

계산과정
  • acc : 0 cur : 1 idx : 0
  • acc : 1 cur : 2 idx : 1
  • acc : 3 cur : 3 idx : 2
  • acc : 6 cur : 4 idx : 3
  • acc : 10 cur : 5 idx : 4
  • acc : 15 cur : 6 idx : 5
  • sum = 21

reduce 2.

ArrayForReduce = [3, 7, 10, 15, 66, 13, 25, 50, 4, 77, 91];
result = ArrayForReduce.reduce((acc, cur, i) => {
  return acc + cur;
});
> 361

위와 같은 방법으로도 reduce를 활용할 수 있지만,
reduce는 사칙연산뿐만 아니라 다양한 기능을 수행할 수 있다.


reduce 3

        result = oneTwoThree.reduce((acc, cur) => {
            acc.push(cur % 2 ? '홀수' : '짝수');
            return acc;
        }, []);
        result; // ['홀수', '짝수', '홀수']

삼항연산자로 홀,짝수를 구할 수 있는 이유
condition ? true : false
위의 예시에서 %2를 통해 나오는 값은 1 또는 0 뿐이다.
true:false는 boolian 값으로 1이 되면 true(홀수), 0이 되면 false(짝수).
끝에 초기값을 배열로 설정하면 map과 같이 사용할 수 있고,
조건을 붙인다면, filter와 같이 사용할 수도 있다.

result = oneTwoThree.reduce((acc, cur) => {
  if (cur % 2) acc.push(cur);
  return acc;
}, []);
result; // [1, 3]
        ```
        const ArrayForReduce = [3,7,10,15,66,13,25,50,4,77,91];
        result = ArrayForReduce.reduce((acc,cur)=>{
        return acc + cur;},0);
        result = 361

reduce 4

배열 내 음수와 양수의 개수를 카운트해서 출력
const numbers = [2, -5, -123, 59, -5480, 24, 0, -69, 349, 3];
const result = numbers.reduce(
  (acc, cur, idx) => {
    if (cur < 0) {
      // 처리할 현재 요소가 음수일 경우
      acc[0]++;
    } else if (cur > 0) {
      // 처리할 현재 요소가 양수일 경우
      acc[1]++;
    }
    return acc;
  },
  [0, 0]
);
console.log(result); // [4, 5]

reduce 5

비동기 프로그래밍
const promiseFactory = (time) => {
  return new Promise((resolve, reject) => {
    console.log(time);
    setTimeout(resolve, time);
  });
};
[1000, 2000, 3000, 4000].reduce((acc, cur) => {
  return acc.then(() => promiseFactory(cur));
}, Promise.resolve());
// 바로 1000
// 1초 후 2000
// 2초 후 3000
// 3초 후 4000
아직 이해하지 못한 개념이다. 초깃값을 Promise.resolve()로 한 후에, return된 프로미스에 then을 붙여 다음 누적값으로 넘기면 된다고 하는데 내가 자유롭게 활용할 수 있을지 지금 실력으로는 어려울 것 같다.





부록. freecordcamp의 reduce 설명

reduce 함수를 통한 객체 생성

the Reduce function takes 2 arguments:
reduce funtion은 2가지 인자를 갖습니다.
1.Callback function: This is a function that contains 4 parameters typically. But right now we are only concerned with the first, the accumulator, and the second which is the current item in the array during that iteration.
콜백함수는 4가지 매개변수를 갖지만, 예시에서는 누산기와 반복하는 동안 배열안의 item을 가져올 수 있게 하는 매개변수만 사용하였습니다.
Initial value: This is the initial value of the accumulator when the iteration starts. In the example above the value is 0, which means the initial value of the accumulator will be 0.
초기값은 반복이 시작될 때 누산기의 초기 값을 의미합니다. 위의 예시에 0은 누산기의 초기 값이 0이라는 것을 의미합니다.

Example

The example will involve counting the number of occurrences of each element in an array, for example:
아래 예시는 입력값으로 준 배열 속 각 요소들에게 발생되는 counting을 어떻게 나타낼 것인지에 대한 예시입니다.

//Given an input //입력값
const fruits = [
  'apples',
  'apples',
  'bananas',
  'oranges',
  'apples',
  'oranges',
  'bananas',
  'grapes',
];

// should give an output of // 기대값
const count = { apples: 3, oranges: 2, bananas: 2, grapes: 1 };

Let's implement the solution, then go through each iteration and see what is happening:
위의 예시를 reduce를 통해 구현해보겠습니다. 구현하는 단계을 하나씩 들여다본다면 reduce 함수가 어떻게 진행되는지 알 수 있습니다.

const fruits = [
  'apples',
  'apples',
  'bananas',
  'oranges',
  'apples',
  'oranges',
  'bananas',
  'grapes',
];

function countOccurrence(accumulator, currentFruit) {
  const currentFruitCount = accumulator[currentFruit];
  if (currentFruitCount) {
    accumulator[currentFruit] = currentFruitCount + 1;
  } else {
    accumulator[currentFruit] = 1;
  }

  return accumulator;
}

const initialValue = {};

const count = fruits.reduce(countOccurrence, initialValue);

The solution is written to be as verbose a possible so we can understand what is going on in the code.
위 예시는 작성된 코드에서 무슨 일이 일어나고 있는지 이해할 수 있도록 가능한 한 장황하게 작성되었습니다.

Iteration 1 In the first iteration, since we made our initial value an empty object, the value of accumulator will be an empty object. This means that the countOcurrence function will look like the code below when it is called:
첫 번째 반복에서 초기 값을 빈 객체로 만들었으므로 accumulator의 값은 빈 객체가 됩니다. 즉, countOcurrence 함수가 호출될 때 아래 코드와 같이 보일 것입니다.

const fruits = [
  'apples',
  'apples',
  'bananas',
  'oranges',
  'apples',
  'oranges',
  'bananas',
  'grapes',
];

// current element is 'apples'

function countOccurrence(accumulator = {}, currentFruit = 'apples') {
  // since currentFruit = 'apples' then accumulator[currentFruit] = accumulator['apples']

  const currentFruitCount = accumulator[currentFruit];
  // currentFruitCount will be null since accumulator is an empty object

  if (currentFruitCount) {
    accumulator[currentFruit] = currentFruitCount + 1;
  } else {
    // this block will run since accumulator is empty
    // currentFruit = 'apples'
    accumulator['apples'] = 1;
    // accumulator should look like this: { 'apples': 1 }
  }

  return accumulator; // which is { 'apples': 1 };

Since accumulator is an empty object, currentFruitCount will be null.

This means that the else block will run where a new key (apples) with the value of 1 will be added to the accumulator.
This will be returned from the function which will be passed as the value of the accumulator in the second iteration.
accumulator는 빈 객체이므로 currentFruitCount는 null이 됩니다. 이는 값이 1인 새 키(사과)가 누산기에 추가되는 곳에서 else 블록이 실행됨을 의미합니다. 이것은 두 번째 반복에서 누산기의 값으로 전달될 함수에서 반환됩니다.

Iteration 2 In the second iteration, our accumulator will have the value of { 'apples': 1 }, which was returned by the countOccurrence function in the first iteration. Then the countOccurrence function will look like the code below:
두 번째 반복에서 누적기는 첫 번째 반복에서 countOccurrence 함수에 의해 반환된 { 'apples': 1 } 값을 갖습니다. 그러면 countOccurrence 함수는 아래 코드와 같이 보일 것입니다.

const fruits = [
  'apples',
  'apples',
  'bananas',
  'oranges',
  'apples',
  'oranges',
  'bananas',
  'grapes',
];

// current element is 'apples'

function countOccurrence(accumulator = { apples: 1 }, currentFruit = 'apples') {
  // since currentFruit = 'apples' then accumulator[currentFruit] = accumulator['apples']

  const currentFruitCount = accumulator[currentFruit];
  // currentFruitCount will be 1

  if (currentFruitCount) {
    // this block will run since currentFruitCount is 1
    // currentFruit = 'apples'
    accumulator['apples'] = 1 + 1;
    // accumulator should look like this: { 'apples': 2 }
  } else {
    accumulator[currentFruit] = 1;
  }

  return accumulator; // which is { 'apples': 2 };

Since the accumulator contains a key ('apple') with the value of 1, currentFruit will be 1, which means the if block will be run. In that block the value of the apple key will be incremented by 1 making it 2, and this new value will be updated in the accumulator object to make it { 'apples' : 2 } . This value will be returned by the countOccurrence function and passed as the value for the accumulator in the third iteration.
누산기에는 값이 1인 키('apple')가 포함되어 있으므로 currentFruit은 1이 되어 if 블록이 실행됩니다. 해당 블록에서 사과 키의 값은 1씩 증가하여 2가 되고 이 새 값은 누산기 개체에서 업데이트되어 { 'apples' : 2 } 가 됩니다. 이 값은 countOccurrence 함수에 의해 반환되고 세 번째 반복에서 누산기의 값으로 전달됩니다.

Iteration 3 For our third iteration, accumulator has the value of { apples: 2 } which was returned by countOccurence during the second iteration. The countOccurence function will look like the code below:
세 번째 반복에서 accumulator는 두 번째 반복 동안 countOccurence에 의해 반환된 { 사과: 2 } 값을 갖습니다. countOccurence 함수는 아래 코드와 같습니다.

const fruits = [
  'apples',
  'apples',
  'bananas',
  'oranges',
  'apples',
  'oranges',
  'bananas',
  'grapes',
];

// current element is 'bananas'

function countOccurrence(
  accumulator = { apples: 2 },
  currentFruit = 'bananas'
) {
  // since currentFruit = 'bananas' then accumulator[currentFruit] = accumulator['bananas']

  const currentFruitCount = accumulator[currentFruit];
  // currentFruitCount will be null since accumulator doesn't contain 'bananas'

  if (currentFruitCount) {
    accumulator[currentFruit] = currentFruitCount + 1;
  } else {
    // this block will run since currentFruitCount is null
    // currentFruit = 'bananas'
    accumulator['bananas'] = 1;
  }

  return accumulator; // which is { 'apples': 2, 'bananas': 1  };
}

This iteration is similar to the first one–since bananas doesn't exist in accumulator it will be added to the object and given a value of 1 , making accumulator look like this: { 'apples': 2, 'bananas': 1 }. This will then become the value of accumulator for the fourth iteration.The process will repeat itself until the Reduce function has iterated through each element in the array.
이 반복은 첫 번째 반복과 유사합니다. 바나나는 누산기에 존재하지 않기 때문에 객체에 추가되고 값 1이 주어집니다. 누산기는 다음과 같이 보입니다. { 'apples': 2, 'bananas': 1 } .
이것은 네 번째 반복의 accumulator 값이 됩니다. 이 프로세스는 Reduce 함수가 배열의 각 요소를 반복할 때까지 반복됩니다.

0개의 댓글