문제 정의
JavaScript에서 카멜 케이스(camelCase)로 작성된 문자열을 받아, 지정한 구분자를 기준으로 단어를 나누고 모두 소문자로 변환하는 함수를 만들어 보겠습니다. 이러한 과정을 흔히 언카멜라이징(uncamelizing)이라고 부릅니다.
함수는 두 개의 인수를 받습니다.
- 첫 번째 인수: 카멜 케이스 문자열 (예:
'thisIsAString') - 두 번째 인수: 단어 사이에 삽입할 구분자 문자 (예:
'_')
함수는 입력 문자열의 단어를 두 번째 인수로 전달된 구분자로 분리하고, 각 단어를 소문자로 변환한 뒤 하나의 문자열로 연결하여 반환해야 합니다.
입력 예시
const str = 'thisIsAString';
const separator = '_';
기대 출력
'this_is_a_string'
구현 코드
다음은 투 포인터(left, right) 방식으로 단어 경계를 찾아 문자열을 분리하는 구현입니다.
const str = 'thisIsAString';
const separator = '_';
const separateCase = (str = '', separator = ' ') => {
const arr = [];
let left = 0, right = 0;
for(let i = 0; i < str.length; i++){
const el = str[i];
const next = str[i + 1];
// 현재 문자가 대문자이거나 마지막 문자인 경우 단어의 끝으로 판단
if((el.toUpperCase() === el && el.toUpperCase() !== el.toLowerCase()) || !next){
right = i + Number(!next);
};
if(left !== right){
const sub = str.substring(left, right).toLowerCase();
arr.push(sub);
left = right;
};
};
return arr.join(separator);
};
console.log(separateCase(str, separator));
코드 동작 원리
- 대문자 감지:
el.toUpperCase() === el && el.toUpperCase() !== el.toLowerCase()조건은 해당 문자가 실제 알파벳이면서 대문자인지 확인합니다. 숫자나 특수문자는 대소문자 구분이 없으므로 이 조건을 통과하지 못합니다. - 마지막 문자 처리:
!next조건은 반복문이 문자열의 끝에 도달했을 때 마지막 단어도 결과에 포함되도록 합니다. - 단어 추출:
substring(left, right)으로 단어를 잘라낸 뒤toLowerCase()로 소문자로 변환하고 배열에 저장합니다. - 결합: 최종적으로
join(separator)을 통해 구분자로 연결된 문자열을 반환합니다.
정규식을 활용한 더 간단한 방법
같은 결과를 replace()와 정규식을 사용해 훨씬 간결하게 구현할 수도 있습니다.
const separateCase = (str = '', separator = ' ') => {
return str.replace(/[A-Z]/g, letter => separator + letter.toLowerCase());
};
console.log(separateCase('thisIsAString', '_'));이 방법은 대문자를 발견할 때마다 앞에 구분자를 붙이고 소문자로 바꾸므로, 코드가 짧고 가독성이 뛰어나 실무에서 널리 사용됩니다.
실행 결과
두 방법 모두 콘솔에 다음과 같은 결과를 출력합니다.
this_is_a_string