IT/Algorithm

프로그래머스) 신규 아이디 추천

프티 2021. 6. 30. 22:34
반응형

https://programmers.co.kr/learn/courses/30/lessons/72410?language=javascript 

 

코딩테스트 연습 - 신규 아이디 추천

카카오에 입사한 신입 개발자 네오는 "카카오계정개발팀"에 배치되어, 카카오 서비스에 가입하는 유저들의 아이디를 생성하는 업무를 담당하게 되었습니다. "네오"에게 주어진 첫 업무는 새로

programmers.co.kr

풀이

 

문자열에서 조건에 부합하지 않는 문자가 있는지 확인하기 위해 리터럴 방식의 정규 표현식과 match 메소드를 활용하였다.

배열로 변환할 때에는 split("")으로 문자 하나씩 나누었다.

' . '의 위치와 2개 이상 붙어있는 경우는 for문에 splice 메소드를 활용하였다.

나머지 2개 이하, 16개 이상인 문자열은 splice 메소드, push 메소드를 활용하여 추가적인 변환을 하였다.

마지막에 join 메소드로 배열 형태에서 다시 문자열로 변환하여 값을 반환한다.

function solution(new_id) {
    var answer = '';

    var fst = new_id.toLowerCase();//1
    var scdNoArr = fst.match(/[^a-z0-9-_.]/g);//조건에 맞지않는 문자 추출
    var scdArr = fst.split("");//배열로 만들기
    
    if(scdNoArr !== null){//2
        for(let i=0; i<scdNoArr.length; i++){
            scdArr.splice(scdArr.indexOf(scdNoArr[i]),1);
        }
    }
    
    for(let i=0; i<scdArr.length; i++){//3, 4
        if(i === 0 && scdArr[i] === '.'){
            scdArr.splice(i,1);
            i--;
        } else if(scdArr.lastIndexOf('.') === scdArr.length-1){
            scdArr.splice(scdArr.length-1,1);
            i--;
        } else if(scdArr[i] === '.' && scdArr[i+1] === '.'){
            scdArr.splice(i,1);
            i--;
        }
    }
    
    if(scdArr.length === 0){//5
        while(scdArr.length < 3){
            scdArr.push('a');
        }
    } else if(scdArr.length > 15){//6
        scdArr.splice(15,scdArr.length-15);
        
        if(scdArr.lastIndexOf('.') === scdArr.length-1){
            scdArr.splice(scdArr.lastIndexOf('.'),1);
        }
    } else if(scdArr.length !== 0 && scdArr.length < 3){//7
        while(scdArr.length < 3){
            scdArr.push(scdArr[scdArr.length-1]);
        }
    }
    
    return scdArr.join("");
}

 

풀이 중 알게된 것

 

문자열에서 검열하고싶은 문자가 여러 개일 때,

정규 표현식에서 중괄호안에서 나열할 수 있다.

 

var scdNoArr = fst.match(/[^a-z-_.]/g);

위 예시는 fst라는 문자열에서 소문자 a~z와 특수문자 ' - ' , ' _ ', ' . '를 제외한( ^ ) 문자를 배열로 반환(match)하라는 코드이다.

 

 

다른 사람의 풀이

function solution(new_id) {
    const answer = new_id
        .toLowerCase() // 1
        .replace(/[^\w-_.]/g, '') // 2
        .replace(/\.+/g, '.') // 3
        .replace(/^\.|\.$/g, '') // 4
        .replace(/^$/, 'a') // 5
        .slice(0, 15).replace(/\.$/, ''); // 6
    const len = answer.length;
    return len > 2 ? answer : answer + answer.charAt(len - 1).repeat(3 - len);
}

간결 그 자체이다..

체이닝을 배웠는데 제대로 써먹지 못한 나를 발견하였다ㅠ

그리고 repeat, replace 메소드를 알게 되었다.

출처 : MDN

regexp에 대응하는 부분을 newSubstr로 대체하는 메소드이다.

이렇게 규칙 순서대로 정규 표현식을 정의하여 replace 메소드를 사용한다.

 

그리고 slice 메소드로 구간을 자르고,

다시 규칙을 적용한다(맨 끝에 ' . '이 있다면 제거하는 규칙).

 

len을 정의하여 삼항 연산자로 길이가 2 이하인 아이디는

 

출처 : MDN

repeat 메소드를 사용하여 아이디 맨 끝의 문자를 길이가 3이 되게끔 맞추어 반복한 문자열을 생성하고,

아이디에 더한다.

 

정규 표현식에 사용한 문자들에 대해서 배운 것들은 다음과 같다.

\ \ + 특수 문자가 아닌 문자 : 문자 그대로 해석하지 않음.
\ + 특수 문자 : 특수 문자 그대로 해석
$와 ^ 정규표현식에서 ^$가 붙어있는 경우,
시작과 끝이 같은 경우 즉, 빈 문자열인 경우에 해당한다.
\w 영숫자를 의미한다. (A-Za-z0-9)
+ \.+의 경우로 설명해보자면,
특수 문자 그대로 ' . '이 옆으로 1회 이상 반복되는 부분에
대응한다는 의미이다.

체이닝을 배운 만큼 자주 사용해서 코드를 더욱 간결하게 짤 수 있도록 해야겠다.

또 정규 표현식을 사용하면 for문이나 forEach 메소드와 같은 방식과 다르게 코드가 더 간단해진는 것을 배웠다.

반응형