ES6 Grammar Essentials (c) - Array

zzwwoonn·2022년 5월 5일
0

React

목록 보기
8/23

배열 함수

가장 자주 사용하는 배열 메소드인 forEach 와 map 그리고 reduce 까지 알아보자.

forEach()

쿼리 스트링(Query String)
웹 주소에 포함시키는 문자열로 사용자가 입력 데이터를 전달하는 방법중의 하나이다. url 주소에 미리 협의된 데이터를 파라미터를 통해 넘기는 것을 말한다.
query parameters(물음표 뒤에 = 로 연결된 key value pair 부분)을 url 뒤에 덧붙여서 추가적인 정보를 서버 측에 전달하는 것이다. 클라이언트가 어떤 특정 리소스에 접근하고 싶어하는지 정보를 담는다.

기존 자바스크립트로 쿼리 스트링 'banana=10 & apple=20 & orange=30'을 & 문자를 기준으로 분리하여 객체에 담아 반환하는 함수(parse)를 만들어보자.

const qs = 'banana=10&apple=20&orange=30';
// 쿼리 스트링

function parse(qs) {
  var queryString = qs.substr(1); 
  // querystring = 'banana=10&apple=20&orange=30'
  
  var chunks = queryString.split('&'); 
  // chunks = ['banana=10', 'apple=20', 'orange=30']
  // => & 문자를 기준으로 먼저 잘라낸다.
  
  var result = {};
  // 결과 담을 객체
  
  for(var i = 0; i < chunks.length; i++) {
    var parts = chunks[i].split('=');
    // = 문자를 기준으로 또 자른다, 그럼 banana랑 10으로 잘려지겠지
    var key = parts[0];
    var value = Number.isNaN(Number(parts[1])) ? parts[1] : Number(parts[1]);
    result[key] = value;
    // key , value 각각으로 변수에 저장해두고 이를 다시 객체에 할당
  }
  return result;
}

가장 보편적인? 방법으로 내가 만약 parse 함수를 만들어야 한다면 위의 코드처럼 짰을 것이다.

위의 코드(parse 함수)는 forEach() 함수를 사용하면 반복문의 순번(i++)과 배열의 크기(chunks length)를 따로 변수에 저장하는 과정을 생략할 수 있다.

function parse(qs) {
  const queryString = qs.substr(1); 
  // querystring = 'banana=10&apple=20&orange=30'
  const chunks = queryString.split('&'); 
  // chunks = ['banana=10', 'apple=20', 'orange=30']
  let result = {};
  
  chunks.forEach((chunk) => {
    const parts = chunk.split('='); 
    // chunk = 'banana=10', parts = ['banana', '10']
    const key = parts[0]
    const value = Number.isNaN(Number(parts[1])) ? parts[1] : Number(parts[1]);
    
    result[key] = value; // result = { banana: 10 }
  });
  return result;
}

이것도 충분히 간편화? 되었다. 하지만 여기서 키와 키값을 구조 분해 할당 방식으로 변화하면 여기서 조금 더 간결하게 바꿀 수 있다. 이게 결론(마지막 코드)이다.

function parse(qs) {
  const queryString = qs.substr(1); 
  // querystring = 'banana=10&apple=20&orange=30'
  const chunks = queryString.split('&'); 
  // chunks = ['banana=10', 'apple=20', 'orange=30']
  let result = {};
  
  chunks.forEach((chunk) => {
    const [ key, value ] = chunk.split('='); 
    // key = 'banana', value = '10'
    result[key] = value; // result = { banana: 10 }
  });
  return result;
}

map()

앞의 예제는 가변 변수(let)을 사용했다. 만약 불변 변수(const)만을 사용해서 짜고 싶다면? map()함수를 쓰면 된다. map 함수는 각 배열 요소를 정의된 함수를 통해 변환한 결과값들로 새 배열을 반환한다.

할당해줄 배열을 왼쪽에 안놔두면 원하는 결과가 안나온다.. 이걸로 삽질 정말 많이 했던 것 같다...

쉽게 말해 배열을 가공하여 새 배열을 만드는 함수이다.

function parse(qs) {
  const queryString = qs.substr(1);
  // querystring = 'banana=10&apple=20&orange=30'
  const chunks = queryString.split('&');
  // chunks = ['banana=10', 'apple=20', 'orange=30']

  const result = chunks.map((chunk) => {
    // 꼭 왼쪽에다가 result 와 같이 새로 만들어진 배열을 할당해줄 변수가 필요하다.
    const [ key, value ] = chunk.split('='); 
    // key = 'banana', value = '10'
    return { key: key, value: value }; 
    // { key: 'banana', value: '10' }
  });
  return result;
  // result = [
  //  { key: 'banana', value: '10'},
  //  { key: 'apple', value: '20' },
  //  { key: 'orange', value: '30'}
  // ];
}

forEach 와 let을 통했을 때의 결과가 동일하게 출력이 나오지만 map()함수는 결과값을 바로 반환하므로 가변 변수를 사용하지 않아도 된다.

reduce()

앞에서 작성한 코드로 얻은 결과값은 배열이다. 만약 이 배열을 객체로 변환하고 싶다면? reduce 함수를 쓰면 된다. reduce 함수의 사용법은 다소 독특하므로 예제를 통해 사용법부터 알아보자.

function sum(numbers) {
  return numbers.reduce((total, num) => total + num, 0);
}
sum([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) // 55

reduce 함수를 이용할 때 인자를 보면 첫 번째 인자로 변환 함수 (total, num) => total + num 이 있고 두 번째 인자로 초기값 0이 있다.

reduce 함수는 변환 함수의 첫 번째 인자를 이전 결과값, 두 번째 인자를 배열의 각 요소들로 생각하여 순환 할당 하면서 함수를 실행한다. 초기값으로 전달한 0은 이전 결과값인 total에 해당한다.

=> 결론적으로 numbers 배열을 계속 돌면서 처음 0이었던 total에다가 계속 더해준다. => 1 + 2 + 3 + ~~ + 9 + 10 = 55

1부터 10까지 더하는 함수라고 생각해도된다.

하지만 실무에서 reduce 함수는 보통 배열을 특정 자료형으로 변환하는데 사용한다고 한다. 즉, 배열의 총합을 구하는 예제(위의 코드)는 '단순히 합을 구하는 예제'가 아니라 '배열을 숫자로 변환한 예제'로 이해해야 한다.

아래 코드는 배열을 객체로 변환하는 과정을 나타낸 코드이다.

function parse(qs) {
  const queryString = qs.substr(1);
  const chunks = queryString.split('&');
  return chunks
    .map((chunk) => {
      const [ key, value ] = chunk.split('='); 
    // key = 'banana', value = '10'
      return { key, value }; 
    // { key: 'banana', value: '10' }
    })
    .reduce((result, item) => {
    //result = {}, item = {key : 'banana', value : '10'}
      result[item.key]: item.value;
    // result = {banana : '10'}
      return result;
    }, {});
}

map 함수가 반환한 배열에는 { key : ~~ , value : ~~~ }의 구조로 구성된 객체들이 들어있을 것이다. (여러 개의 객체들이 배열에 주르륵 들어있겠지?) reduce() 함수에서 item이 배열을 순회한다. 이 때 item 은 그 객체 하나하나 이고 key를 키값으로, value를 값으로 하는 하나의 객체로 반환한다.

최종 반환값
=> result : {banana : '10', apple : '20', orange : '30'}
배열이 객체로 반환되었다.

0개의 댓글