본문 바로가기
언어/javascript | typescript

데이터 재가공을 위해 사용할 때 유용한 함수 map과 reduce

by code_yull 2022. 1. 28.

 

최대한 많이 재사용할 수 있도록 작성한 쿼리문을 작성하고 데이터를 가지고 오게 되면,
원하는 형태로 데이터를 보여주기 위해 다양한 함수를 사용하여 재가공하게 된다.

해당 아티클에서는 앱잼기간 동안 실제로 데이터 재가공을 위해 사용했던 함수들을 소개하고,
어떤 상황에서 어떻게 사용했는지 예시를 들어보려고 한다.

Array.map()

arr.map(callback(currentValue[, index[, array]])[, thisArg])
arr.map((요소, 인덱스, 배열) ⇒ {return 요소})

 

매개변수

더보기
  • callback
    새로운 배열 요소를 생성하는 함수. 다음 세 가지 인수를 가집니다.
    - currentValue 처리할 현재 요소.
    - index (Optional) 처리할 현재 요소의 인덱스.
    - array (Optional) map()을 호출한 배열.
  • thisArg (Optional)
    callback을 실행할 때 this로 사용되는 값.

 

배열을 순환하면서 해당 인덱스의 값을 원하는 형태로 가공하여 새로운 배열안에 넣어 리턴해주며, 기존 배열은 수정되지 않는다.

공식문서에 나와있는 가장 기본의 예시는 아래와 같다.

const array1 = [1, 4, 9, 16];

// pass a function to map
const map1 = array1.map(x => x * 2);

console.log(map1);
// expected output: Array [2, 8, 18, 32]

위의 예시처럼 간단하게 사용하는 것뿐만 아니라 배열 내부의 값에 일대일로 해당하는 값을 담은 배열을 생성하고 싶을 때 간편하게 사용가능하다.


  • 예제1.
    float값들을 담고있는 array1이 있다.
    float값들의 반올림한 값들을 담은 새로운 배열 map1을 반환받는다.
  • // 예제1
    const array1 = [1.2, 1.4, 5, 7.9];
    const map1 = array1.map(x => Math.round(x))
    // map1 = [1, 1, 5, 8]
  • 예제2.
    array2배열 안의 값들을 새로운 객체의 value값으로 가진 객체를 담은 배열을 반환받는다.
  • // 예제2
    const array2 = ["사과", "바나나", "오렌지"];
    const map2 = array2.map(x => JSON.parse(`{"ObjectValue": ${x}}`));
    // map2 = [{"ObjectValue": "사과"}, {"ObjectValue": "바나나"}, {"ObjectValue": "오렌지"}]

실제 코드에서는 아래와 같이 사용하였다.

  • 배열로 req를 받아온 경우, 배열 안의 값을 쿼리 WHERE IN문 안에서 사용하기 위해
    (teamId, userId), (teamId, userId) 형태로 teamId와 함께 가공하기
    🌟 Array.join() 메서드는 배열 안의 값을 꺼내서 string으로 만들어준다.
  • const userIdList = '[1, 2]';
    const teamId = 10
    const valuesInsertQuery = JSON.parse(userIdList).map((x) => `(${teamId}, ${x})`).join(', ');
    // 결과값 (10, 1), (10, 2)
  • 객체 배열에서 객체값의 특정 키에 해당하는 밸류 값만 가져오기
  • const array = [{"id": 1, "name": "hi"}, {"id": 2, "name": "hey"}, {"id": 3, "name": "wow"}]
    const result = array.map(x => x.name)
    // 결과값 ["hi", "hey", "wow"]

Array.reduce()

arr.reduce(callback[, initialValue])
배열.reduce((누적값, 현재값, 인덱스, 요소) => {return 결과}, 초기값)

 

매개변수

더보기
  • callback
    배열의 각 요소에 대해 실행할 함수. 다음 네 가지 인수를 받습니다.
    - accumulator 누산기는 콜백의 반환값을 누적합니다. 콜백의 이전 반환값 또는, 콜백의 첫 번째 호출이면서 initialValue를 제공한 경우에는 initialValue의 값입니다.
    - currentValue 처리할 현재 요소.
    - currentIndex (Optional) 처리할 현재 요소의 인덱스. initialValue를 제공한 경우 0, 아니면 1부터 시작합니다.
    - array (Optional) reduce()를 호출한 배열.
  • initialValue (Optional) 
    callback의 최초 호출에서 첫 번째 인수에 제공하는 값. 초기값을 제공하지 않으면 배열의 첫 번째 요소를 사용합니다. 빈 배열에서 초기값 없이 reduce()를 호출하면 오류가 발생합니다.

 

map과 마찬가지로 배열을 순환하지만, map과 달리 reduce는 전 인덱스를 거쳐오면서 누적된 누적값을 매개변수로 갖고, 하나의 값을 반환한다. 해당 인덱스에서 연산이 끝나고 나면 다음 인덱스로 넘어가면서 결과값을 누적값(acc)이라는 매개변수로 받아간다.

또한 초기값을 설정해줄 수 있어서, 0번째 인덱스 값을 받아오기 전에 어떤 초기값에서 연산을 시작할 것인지 설정할 수도 있다.

공식문서에 나와있는 가장 기본의 예시는 아래와 같다.

const array1 = [1, 2, 3, 4];
const reducer = (previousValue, currentValue) => previousValue + currentValue;

// 1 + 2 + 3 + 4
console.log(array1.reduce(reducer));
// expected output: 10

// 5 + 1 + 2 + 3 + 4
console.log(array1.reduce(reducer, 5));
// expected output: 15

예시 코드에서는 하나의 int값을 반환했지만, reduce함수로는 하나의 값 뿐만 아니라, 배열, 객체까지도 반환받을 수 있다.


  • 예제 1.
    map함수의 기본 예시를 reduce함수로 구현하기초기 값을 []로 설정하고, 콜백함수에서 배열에 cur * 2 값을 밀어넣게 하였으므로, 결과적으로 배열 값이 반환된다.
  • // map함수 기본 예시 
    const array1 = [1, 4, 9, 16]; 
    const map1 = array1.map(x => x * 2); 
    // 결과 [2, 8, 18, 32] 
    
    // reduce로 구현하기 
    const reduce1 = array1.reduce( (acc, cur, i) => { console.log(acc, cur, i); 
        return acc.push(cur * 2); }, []);
    
    /* 로그에 출력되는 것 
    * [], 1, 0 
    * [2], 4, 1 
    * [2, 8], 9, 2 
    * [2, 8, 18], 16, 3 
    */
    // 최종 반환값 [2, 8, 18, 32]
  • 예제 2.
    비동기 프로그래밍과 함께 사용하기reduce와 promise를 사용하여 리스트내의 값들이 돌아가면서 1초후 출력되도록 했다.
  • const promise = (x) => { return new Promise((resolve, reject) => { 
        console.log(x); setTimeout(resolve, 1000); 
    }); }; 
    
    ['하나', '둘', '셋', '얍'].reduce((acc, cur) => { 
        return acc.then(() => promise(cur)); 
    }, Promise.resolve());

실제 코드에서는 아래와 같이 사용하였다.

  • 리스트 안의 값을 객체 배열 속 객체 안에 집어넣기
  • const idList = [1, 2, 3, 4];
    const answerObjectArray = idList.reduce((acc, cur) => { 
        acc.push({id: cur}); 
        return acc
    }, []); 
    
    // 반환값 [{id: 1}, {id: 2}, {id: 3}, {id: 4}]

댓글