문제: https://school.programmers.co.kr/learn/courses/30/lessons/72410
코딩테스트 연습 > 2021 KAKAO BLIND RECRUITMENT
단계별 조건에 따라 구현한다
정규식 / 자바스크립트 내장함수 / 문자열 조작 순서를 공부해야 한다
function solution(new_id) {
new_id = new_id.toLowerCase(); // 1단계
let result = ''; // 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.)만 남길 문자열
for(let i = 0; i < new_id.length; i++){
const char = new_id[i];
if((char >= 'a' && char <= 'z')||
(char >= '0' && char <= '9')||
(char === '-') ||
(char === '_')||
(char === '.')
){
result += char;
}
}
new_id = result;
result = ''; // 초기화
for(let i = 0; i < new_id.length; i++){
if(new_id[i] === '.' && new_id[i+1] === '.'){
continue;
}
result += new_id[i];
}
new_id = result;
if(new_id.length > 0 && new_id[0] === '.') {
new_id = new_id.substring(1);
}
if(new_id.length > 0 && new_id[new_id.length - 1] === '.'){
new_id = new_id.substring(0, new_id.length - 1);
}
if(new_id === ''){
new_id = 'a';
}
if(new_id.length >= 16){
new_id = new_id.substring(0, 15);
if(new_id[new_id.length - 1] === '.'){
new_id = new_id.substring(0, new_id.length - 1);
}
}
while(new_id.length <= 2){
new_id += new_id[new_id.length - 1];
}
return new_id;
}
function solution(new_id) {
// 1단계: 대문자를 소문자로 치환
new_id = new_id.toLowerCase();
// 2단계: 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.)를 제외한 모든 문자 제거
new_id = new_id.replace(/[^\w\-\.]/g, '');
// \w는 알파벳, 숫자, 밑줄(_)을 포함하는 문자 클래스
// \-는 빼기 기호, \.는 마침표를 나타냄
// 3단계: 마침표(.)가 2번 이상 연속된 부분을 하나의 마침표로 치환
new_id = new_id.replace(/\.{2,}/g, '.');
// 4단계: 마침표(.)가 처음이나 끝에 위치한다면 제거
new_id = new_id.replace(/^\.|\.$/g, '');
// 5단계: 빈 문자열이라면, "a"를 대입
if (new_id === '') {
new_id = 'a';
}
// 6단계: 길이가 16자 이상이면, 첫 15개 문자를 제외한 나머지 문자들을 모두 제거
if (new_id.length >= 16) {
new_id = new_id.slice(0, 15);
// 제거 후 마침표(.)가 끝에 위치한다면 제거
new_id = new_id.replace(/\.$/, '');
}
// 7단계: 길이가 2자 이하라면, 마지막 문자를 길이가 3이 될 때까지 반복해서 붙임
while (new_id.length <= 2) {
new_id += new_id.charAt(new_id.length - 1);
}
return new_id;
}
메서드 체이닝과 자바스크립트 내장함수 .padEnd()
를 이용해 조금더 코드를 간결하게 개선할 수 있다.
function solution(new_id) {
return new_id
.toLowerCase() // 1단계: 소문자로 변환
.replace(/[^\w\-\.]/g, '') // 2단계: 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.)를 제외한 모든 문자 제거
.replace(/\.{2,}/g, '.') // 3단계: 마침표(.)가 2번 이상 연속된 부분을 하나의 마침표로 치환
.replace(/^\.|\.$/g, '') // 4단계: 처음과 끝의 마침표 제거
.replace(/^$/, 'a') // 5단계: 빈 문자열이면 'a' 대입
.slice(0, 15) // 6단계: 길이가 16자 이상이면, 첫 15개 문자만 남김
.replace(/\.$/, '') // 6단계: 끝에 마침표가 있으면 제거
.padEnd(3, new_id.slice(-1) || 'a'); // 7단계: 길이가 2자 이하라면, 마지막 문자를 길이가 3이 될 때까지 반복
}
replace(/[^\w\-\.]/g, '')
\w
: 알파벳, 숫자, 밑줄(_)을 포함하는 문자 클래스
\-\.
: 빼기(-), 마침표(.)
[^...]
: 괄호 안의 문자를 제외한 모든 문자와 매칭
따라서, 허용된 문자 외의 모든 것이 제거 됨
replace(/\.{2,}/g, '.')
\.{2,}
: 마침표가 2번 이상 연속된 부분 → 이를 하나의 마침표로 치환
replace(/^\.|\.$/g, '')
^\.
: 문자열 시작의 마침표
\.$
: 문자열 끝의 마침표
이 두 가지 경우를 모두 빈 문자열로 대체
replace(/^$/, 'a')
^$
: 빈 문자열에 매칭
빈 문자열인 경우 'a'로 대체
slice(0, 15)
문자열을 처음부터 15자까지만 남긴다
길이가 15 미만이면 전체 문자열이 그대로 유지한다
replace(/\.$/, '')
길이 제한 후 끝에 마침표가 있다면 제거
padEnd(3, new_id.slice(-1) || 'a')
padEnd(3, ...)
: 문자열 길이가 3이 될 때까지 지정된 문자로 채운다
new_id.slice(-1) || 'a'
: 마지막 문자(없으면 'a'를 사용)길이가 1이나 2인 경우 마지막 문자를 반복해 길이가 3이 되게 한다
7단계에서 new_id.slice(-1)
은 원본 new_id의 마지막 문자를 가져오는 것이 아니라, 체이닝 과정에서 현재 변환된 문자열의 마지막 문자를 가져온다
빈 문자열이 될 경우 slice(-1)은 빈 문자열을 반환하므로, || 'a'를 통해 기본값 'a'를 제공해야 한다