문제 상황
다음과 같은 특수한 형식의 문자열이 있다고 가정해 보겠습니다.
const str = "Integer,1 Float,2.0\nBoolean,True Integer,6\nFloat,3.66 Boolean,False";
이 문자열을 String.prototype.split() 메서드를 활용해 아래와 같은 객체 배열로 변환하는 JavaScript 함수를 작성하는 것이 목표입니다.
const arr = [
{
"Integer": 1,
"Float": 2.0
},
{
"Boolean": true,
"Integer": 6
},
{
"Float": 3.66,
"Boolean": false
}
];
변환 규칙
문자열을 배열로 변환할 때는 다음 세 가지 규칙을 적용합니다.
\n(줄바꿈): 하나의 객체, 즉 배열 요소 하나의 끝을 의미합니다.- 공백 한 칸: 객체 내부에서 개별 키/값 쌍을 구분합니다.
- 쉼표(
,): 각 쌍에서 키와 값을 분리합니다.
구현 코드
위 규칙에 따라 작성한 변환 함수는 다음과 같습니다.
const str = "Integer,1 Float,2.0\nBoolean,True Integer,6\nFloat,3.66 Boolean,False";
const stringToArray = str => {
const strArr = str.split('\n');
return strArr.map(el => {
const elArr = el.split(' ');
return elArr.map(elm => {
const [key, value] = elm.split(',');
return {
[key]: value
};
});
});
};
console.log(stringToArray(str));
코드 동작 원리
split('\n')으로 전체 문자열을 줄바꿈 기준으로 잘라 객체 단위로 분리합니다.map()으로 각 줄을 순회하며split(' ')으로 공백 기준 키/값 쌍을 나눕니다.- 각 쌍을
split(',')으로 다시 분해해 키와 값을 추출하고, 계산된 속성명(computed property name) 문법인[key]를 사용해 객체를 생성합니다.
실행 결과
위 코드를 실행하면 콘솔에 다음과 같이 출력됩니다.
[
[ { Integer: '1' }, { Float: '2.0' } ],
[ { Boolean: 'True' }, { Integer: '6' } ],
[ { Float: '3.66' }, { Boolean: 'False' } ]
]
심화: 값의 자료형까지 변환하기
기본 구현에서는 모든 값이 문자열로 반환됩니다. 처음 의도했던 것처럼 숫자와 불리언 타입으로 변환된 결과를 얻으려면 값을 판별하는 과정을 추가하면 됩니다.
const stringToArrayTyped = str =>
str.split('\n').map(line =>
line.split(' ').map(pair => {
const [key, raw] = pair.split(',');
let value;
if (raw === 'True') value = true;
else if (raw === 'False') value = false;
else if (!isNaN(raw)) value = Number(raw);
else value = raw;
return { [key]: value };
})
);
console.log(stringToArrayTyped(str));
이 버전은 문자열 'True'/'False'를 불리언으로, 숫자 형태의 문자열은 Number()로 변환해 다음과 같은 결과를 반환합니다.
[
[ { Integer: 1 }, { Float: 2 } ],
[ { Boolean: true }, { Integer: 6 } ],
[ { Float: 3.66 }, { Boolean: false } ]
]
이처럼 split()과 map()만 조합하면 별도의 파싱 라이브러리 없이도 구조화된 문자열을 손쉽게 객체 배열로 변환할 수 있습니다.