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

JavaScript에서 split()과 reduce()로 배열 문자열을 중첩 객체로 변환하는 방법

문제 소개

JavaScript를 다루다 보면 일정한 패턴을 가진 문자열 배열을 구조화된 객체로 변환해야 하는 경우가 자주 발생합니다. 이번 글에서는 하이픈(-)으로 구분된 문자열 배열을 브랜드별 모델 출현 횟수를 담은 중첩 객체로 변환하는 방법을 단계별로 살펴보겠습니다.

문제 상황

다음과 같이 "브랜드-모델" 형태의 문자열로 이루어진 배열이 있다고 가정해 보겠습니다.

const arr = [
  "fiat-palio",
  "fiat-stilo",
  "fiat-strada",
  "fiat-uno",
  "fiat-uno",
  "gm-corsa",
  "gm-celta",
  "ford-fiesta",
  "volkswagen-gol",
  "volkswagen-gol",
  "volkswagen-gol",
  "volkswagen-voyage"
];

배열의 모든 요소는 하나의 공통점을 가지고 있습니다. 바로 하이픈(-)으로 구분된 두 개의 문자열 쌍(브랜드와 모델)으로 이루어져 있다는 점입니다.

요구 사항

이 배열을 입력받아 다음 조건을 만족하는 객체를 반환하는 함수를 작성해야 합니다.

  • 객체의 키(key)는 하이픈 앞부분, 즉 브랜드 이름입니다.
  • 각 키의 값(value)은 해당 브랜드에 속한 모델 이름과 그 모델이 원본 배열에 등장한 횟수를 담은 객체입니다.

기대 결과

위 배열을 변환하면 다음과 같은 결과가 나와야 합니다.

const output = {
  "fiat": {
    "palio": 1,
    "stilo": 1,
    "strada": 1,
    "uno": 2
  },
  "gm": {
    "corsa": 1,
    "celta": 1
  },
  "ford": {
    "fiesta": 1
  },
  "volkswagen": {
    "gol": 3,
    "voyage": 1
  }
};

"fiat-uno"는 두 번 등장했으므로 uno의 값이 2가 되고, "volkswagen-gol"은 세 번 등장했으므로 gol의 값이 3이 되는 것을 확인할 수 있습니다.

구현 코드

split()reduce()를 활용한 전체 코드는 다음과 같습니다.

const arr = [
  "fiat-palio",
  "fiat-stilo",
  "fiat-strada",
  "fiat-uno",
  "fiat-uno",
  "gm-corsa",
  "gm-celta",
  "ford-fiesta",
  "volkswagen-gol",
  "volkswagen-gol",
  "volkswagen-gol",
  "volkswagen-voyage"
];

const convertToObject = (arr = []) => {
  let res = arr.reduce((acc, val) => {
    let pair = val.split('-');
    let mark = pair[0];   // 브랜드
    let model = pair[1];  // 모델
    if (!acc.hasOwnProperty(mark)) {
      acc[mark] = {};
      acc[mark][model] = 1;
    } else {
      if (acc[mark].hasOwnProperty(model)) {
        acc[mark][model] += 1;
      } else {
        acc[mark][model] = 1;
      }
    }
    return acc;
  }, {});
  return res;
};

console.log(convertToObject(arr));

코드 동작 원리

  1. split('-'): 각 문자열을 하이픈 기준으로 나누어 [브랜드, 모델] 형태의 배열을 만듭니다.
  2. reduce(): 초기값으로 빈 객체({})를 설정하고, 배열을 순회하면서 누적 객체(acc)를 점차 완성해 갑니다.
  3. hasOwnProperty(): 해당 브랜드 또는 모델 키가 이미 존재하는지 확인합니다. 존재하지 않으면 새로 생성해 값을 1로 설정하고, 이미 존재하면 기존 값을 1 증가시킵니다.

참고로, 논리 연산자를 활용하면 위 로직을 더욱 간결하게 표현할 수도 있습니다.

const convertToObject = (arr = []) =>
  arr.reduce((acc, val) => {
    const [mark, model] = val.split('-');
    acc[mark] = acc[mark] || {};
    acc[mark][model] = (acc[mark][model] || 0) + 1;
    return acc;
  }, {});

실행 결과

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

{
  fiat: { palio: 1, stilo: 1, strada: 1, uno: 2 },
  gm: { corsa: 1, celta: 1 },
  ford: { fiesta: 1 },
  volkswagen: { gol: 3, voyage: 1 }
}

이처럼 split()으로 문자열을 분리하고 reduce()로 데이터를 누적하는 패턴은 로그 집계, 태그 카운트, 그룹핑 등 다양한 실무 상황에서 유용하게 활용할 수 있습니다.