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

자바스크립트에서 점(.) 구분 문자열을 중첩 객체로 변환하는 방법

문제 개요

점(.)으로 구분된 문자열 배열을 입력받아, 각 문자열의 계층 구조를 그대로 반영하는 객체를 반환하는 자바스크립트 함수를 작성해야 합니다.

예를 들어, 다음과 같은 배열이 있다고 가정해 보겠습니다.

const arr = [
    "country.UK.level.1",
    "country.UK.level.2",
    "country.US.level.1",
    "country.UK.level.3"
];

이 배열을 변환하면 아래와 같은 형태의 결과가 나와야 합니다.

const output = {
    "country": [
        {"UK" : {"level" : ["1", "2", "3"]}},
        {"US" : {"level" : ["1","2"]}}
    ]
}

조건

  • 배열에 저장된 문자열은 정렬되어 있지 않으며, 코드는 정렬 여부와 관계없이 안정적으로 동작해야 합니다.
  • 문자열은 x.y.x.y... 패턴을 따릅니다. 여기서 x 위치(country, level)는 항상 고정되고, y 위치(UK, US, 1, 2 등)는 달라질 수 있습니다.
  • 문자열의 길이에는 제한이 없습니다. 문자열이 길어질수록 객체의 중첩 깊이도 깊어지므로, 재귀적 또는 반복적인 순회 방식으로 처리해야 합니다.

구현 코드

다음은 위 조건을 만족하는 전체 코드입니다.

const arr = [
    "country.UK.level.1",
    "country.UK.level.2",
    "country.US.level.1",
    "country.UK.level.3"
];
const stringToObject = arr => {
    const obj = {};
    arr.forEach(str => {
        let curr = obj;
        let splitted = str.split('.');
        let last = splitted.pop();
        let beforeLast = splitted.pop();
        splitted.forEach( sub => {
            if(!curr.hasOwnProperty(sub)){
                curr[sub] = {};
            };
            curr = curr[sub];
        });
        if(!curr[beforeLast]){
            curr[beforeLast] = [];
        };
        curr[beforeLast].push(last);
    });
    return obj;
};
console.log(JSON.stringify(stringToObject(arr), undefined, 4));

코드 동작 원리

이 코드의 핵심 로직은 다음과 같이 단계별로 이해할 수 있습니다.

  1. 문자열 분리: split('.') 메서드로 각 문자열을 점 기준으로 나눕니다. 예를 들어 "country.UK.level.1"은 ["country", "UK", "level", "1"]이 됩니다.
  2. 마지막 두 요소 추출: pop()을 두 번 호출하여 마지막 값(1)과 그 바로 앞 키(level)를 분리합니다.
  3. 중간 경로 생성: 남은 요소들(country, UK)을 순회하면서 hasOwnProperty로 기존 키 존재 여부를 확인하고, 없으면 빈 객체({})를 새로 만듭니다. 이 과정에서 참조 변수 curr가 한 단계씩 깊숙이 이동합니다.
  4. 값 저장: 최종 위치에서 beforeLast(level) 키에 배열이 없으면 새 배열을 초기화한 뒤, last(1) 값을 push합니다.

이 방식 덕분에 문자열이 몇 단계로 구성되어 있더라도 동일한 로직으로 처리할 수 있으며, 이미 존재하는 경로는 중복 생성하지 않으므로 정렬되지 않은 입력에도 문제없이 동작합니다.

실행 결과

위 코드를 실행하면 콘솔에 다음과 같은 출력이 나타납니다.

{
    "country": {
        "UK": {
            "level": [
                "1",
                "2",
                "3"
            ]
        },
        "US": {
            "level": [
                "1"
            ]
        }
    }
}

결과를 보면 country 아래에 UK와 US가 각각 객체로 배치되고, 각 국가의 level 키에는 해당하는 레벨 값들이 배열로 수집된 것을 확인할 수 있습니다. UK에는 1, 2, 3이 모두 포함되지만, US에는 입력 데이터에 1만 존재하므로 1만 담기게 됩니다.