map reduce

mangojang·2023년 1월 3일
0

map

  • 배열.map((요소, 인덱스, 배열) => { return 요소 }[this인자]);
  • callback함수의 요소, 배열 그리고 this인자는 옵션.
  • 배열 안의 요소와 return 값의 요소를 1:1 로 짝지어 반환함.
  • 어떻게 짝 지어 반환 할지는 callback 함수로 정의 하여 map의 인자로 넣어줌.
  • return 값과 호출한 배열의 값은 서로 다른 값이다.
    (얕은 복사 - 배열 안에 객체가 있는 경우, 객체는 공유 됨. )
    ```jsx
    const array = [1, 4, 9, 16];
    const map = array.map(x => x);
    
    console.log(map); // [1, 4, 9, 16]
    console.log('둘은 같은 값인가?', array===map); // false
    ```
  • callback 함수에서 호출한 배열이 변경 될 수는 있음.

사용 패턴

  1. 새로운 형태의 값 생성하기

    const kvArray = [{key:1, value:10},
                   {key:2, value:20},
                   {key:3, value: 30}];
    
    const reformattedArray = kvArray.map(obj => { 
       let rObj = {};
       rObj[obj.key] = obj.value;
       return rObj;
    });
    
    console.log(reformattedArray) // [{1:10}, {2:20}, {3:30}]
  2. 특정 요소 재정의 하기

    const kvArray = [{key:1, value:10},
                   {key:2, value:20},
                   {key:3, value: 30}];
    const reformattedArray = kvArray.map(obj => {
        if (obj.key === '2') {
            return { ...obj, value: 40 };
        }
    
        return { ...obj };
    });
    
    console.log(reformattedArray)  
    // [{key:1, value:10},
    //  {key:2, value:40},
    //  {key:3, value: 30}]
  3. 문자를 배열로 바꾸기

    const word = 'mangojang';
    const wordArray = Array.prototype.map.call(word, char =>`${char}`)
    
    console.log(wordArray); // ['m','a','n','g','o','j','a','n','g']
  4. querySelectorAll 순회 처리

    const elems = document.querySelectorAll('input[type=checkbox]:checked');
    var values = [].map.call(elems, obj => obj.value);

reduce

  • 배열.reduce((누적값, 현잿값, 인덱스, 배열) => { return 결과 }, 초깃값);
    • return 값은 누적값에 할당되고, 순회 중 유지 되므로 최종 결과 값은 하나의 값이 됨.
    • callback 함수의 인덱스, 배열 그리고 초깃값은 옵션.
    • 초깃값을 안 적을 경우, 초깃값은 배열의 0번째 값이 됨.
      const array = [1,2,3,4]
      
      let containInitValue= array.reduce(function(accumulator, currentValue, currentIndex, array) {
        console.log(accumulator, currentValue, currentIndex);
      	return accumulator + currentValue;
      },0);
      
      // 0 1 0
      // 1 2 1
      // 3 3 2
      // 6 4 3
      console.log(containInitValue) //10
      
      let notContainInitValue= array.reduce(function(accumulator, currentValue, currentIndex, array) {
        console.log(accumulator, currentValue, currentIndex);
      	return accumulator + currentValue;
      });
      
      // 1 2 1
      // 3 3 2
      // 6 4 3
      console.log(notContainInitValue) //10
  • 초깃값을 어떤 타입을 넣느냐에 따라 반환값을 다양하게 받을 수 있음.
  • return 값과 호출한 배열의 값은 서로 다른 값이다.
    (얕은 복사 - 배열 안에 객체가 있는 경우, 객체는 공유 됨. )
  • callback 함수에서 호출한 배열이 변경 될 수는 있음.

사용 패턴

  1. 객체 배열에서의 값 연산

    • 객체로 이루어진 배열의 연산에서는 반드시 초깃값을 주어야 함.
    const list = [
        {
            x : 1
        },
        {
            x : 2
        },
        {
            x : 3
        }
    ];
    const sum = list.reduce((accumulator, currentValue) => 
        accumulator + currentValue.x;
    , 0)
    
    console.log(sum) // 6
  2. 중첩 배열 펼치기

    const flattened = [[0, 1], [2, 3], [4, 5]].reduce(
      (accumulator, currentValue) => 
        accumulator.concat(currentValue);
      ,
      [] // 초깃값: 빈 배열
    );
  3. 속성으로 객체 분류

    const people = [
      { name: 'Alice', age: 21 },
      { name: 'Max', age: 20 },
      { name: 'Jane', age: 20 }
    ];
    
    function groupBy(objectArray, property) {
      return objectArray.reduce(function (acc, obj) {
        let key = obj[property];
        if (!acc[key]) {
          acc[key] = [];
        }
        acc[key].push(obj);
        return acc;
      }, {});
    }
    
    const groupedPeople = groupBy(people, 'age');
    console.log(groupedPeople)
    // {
    //   20: [
    //     { name: 'Max', age: 20 },
    //     { name: 'Jane', age: 20 }
    //   ],
    //   21: [{ name: 'Alice', age: 21 }]
    // }
  4. 중복 항목 제거

    let arr = [1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4];
    let result = arr.sort().reduce((accumulator, current) => {
        const length = accumulator.length
        if (length === 0 || accumulator[length - 1] !== current) {
            accumulator.push(current);
        }
        return accumulator;
    }, []);
    console.log(result); //[1,2,3,4,5]
  5. reducer로 map 함수 표현 하기

    • 초깃값을 빈 배열로 두고, push하는 형식으로 map함수를 표현
    const array = [1,2,3,4]
    const reducer = array.reduce((acc,cur)=>acc.push(cur), []);
    
    console.log(reducer) // [1,2,3,4]
  6. reducer로 filter 함수 표현 하기

    • 조건에 따라 push 하는 값을 다르게 함.

    ▶️ 이런 식으로 sort, every, some, find, findIndex, includes 도 구현 가능.

    const array = [1,2,3,4]
    const reducer = array.reduce((acc,cur)=>{
    	if(cur%2){ acc.push(cur)}
    	return acc;
    },[]);
    
    console.log(reducer) // [1,3]
  7. 프로미스 순차적으로 실행

    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

차이점

이 글의 처음 질문인 ‘map 과 reduce의 차이가 무엇인가?’ 의 답은
return 받는 값의 방식이 다르다는 것이다.
map은 호출하는 배열 안의 요소와 return 값의 요소가 1:1 로 짝지어 반환되고,
reduce는 return 값이 누적값에 할당되는 형식으로 최종으로는 하나의 결과값이 반환된다. ⇒ reduce는 더 다양한 형식으로 return 값을 받을 수 있다.

참고 문헌

profile
한 걸음 한 걸음 계속 걷는 자가 일류다

0개의 댓글