Computer >> 컴퓨터 >  >> 프로그래밍 >> JavaScript

JavaScript에서 첫 번째 요소를 기준으로 배열 그룹화하기

JavaScript로 개발을 하다 보면 중첩 배열의 데이터를 특정 기준에 따라 묶어야 하는 경우가 자주 발생합니다. 이번 글에서는 배열의 첫 번째 요소가 같은 값끼리 두 번째 요소들을 하나의 배열로 그룹화하는 방법을 알아보겠습니다.

문제 상황

다음과 같이 숫자 쌍으로 이루어진 중첩 배열이 있다고 가정해 봅시다.

const arr = [[1, 45], [1, 34], [1, 49], [2, 34], [4, 78], [2, 67], [4, 65]];

각 하위 배열은 반드시 정확히 두 개의 요소를 가지고 있습니다. 여기서 우리가 작성해야 할 함수는 다음과 같은 역할을 수행해야 합니다.

  • 하위 배열들의 첫 번째 값(first value)을 기준으로 판단합니다.
  • 첫 번째 값이 서로 같은 하위 배열들의 두 번째 값(second value)들을 모아 하나의 새로운 배열로 만듭니다.

따라서 위 배열을 처리한 결과는 아래와 같은 형태가 되어야 합니다.

const output = [
   [45, 34, 49],
   [34, 67],
   [78, 65]
];

첫 번째 값이 1인 요소들은 [45, 34, 49]로, 2인 요소들은 [34, 67]로, 4인 요소들은 [78, 65]로 각각 그룹화된 것을 확인할 수 있습니다.

해결 방법: reduce()와 Map() 활용하기

이 문제는 Array.prototype.reduce() 메서드와 Map() 객체를 함께 사용하면 깔끔하게 해결할 수 있습니다.

  • reduce(): 배열을 순회하면서 누적 결과(accumulator)를 만들어 갑니다.
  • Map(): 첫 번째 값과 결과 배열 내 인덱스를 매핑하여, 이미 존재하는 그룹인지 빠르게 확인합니다.

코드 구현

전체 코드는 다음과 같습니다.

const arr = [[1, 45], [1, 34], [1, 49], [2, 34], [4, 78], [2, 67], [4, 65]];

const constructSimilarArray = (arr = []) => {
   const creds = arr.reduce((acc, val) => {
      const { map, res } = acc;
      if(!map.has(val[0])){
         map.set(val[0], res.push([val[1]]) - 1);
      }else{
         res[map.get(val[0])].push(val[1]);
      };
      return { map, res };
   }, {
      map: new Map(),
      res: []
   });
   return creds.res;
};

console.log(constructSimilarArray(arr));

동작 원리 살펴보기

  1. 초기값 설정: reduce()의 초기값으로 map(그룹 키와 인덱스를 저장하는 Map 객체)과 res(최종 결과 배열)를 담은 객체를 전달합니다.
  2. 새로운 그룹인 경우: map.has(val[0])가 false라면, 해당 첫 번째 값이 처음 등장한 것이므로 res에 새 배열을 추가하고, 그 인덱스를 Map에 저장합니다. 참고로 JavaScript의 push() 메서드는 배열의 새 길이를 반환하므로, 여기서 1을 빼면 방금 추가된 요소의 실제 인덱스가 됩니다.
  3. 기존 그룹인 경우: Map에 이미 키가 존재한다면, 저장된 인덱스를 이용해 res의 해당 그룹 배열에 두 번째 값을 추가(push)합니다.
  4. 결과 반환: 순회가 끝나면 creds.res, 즉 그룹화된 최종 배열을 반환합니다.

실행 결과

콘솔에 출력되는 결과는 다음과 같습니다.

[ [ 45, 34, 49 ], [ 34, 67 ], [ 78, 65 ] ]

마무리

이처럼 reduce()Map()을 조합하면 별도의 외부 변수 없이 함수형 프로그래밍 스타일로 데이터를 그룹화할 수 있습니다. 이 패턴은 키 기반 데이터 집계, 카테고리별 분류 등 다양한 상황에서 응용할 수 있으니 꼭 기억해 두시기 바랍니다.