티스토리 뷰

728x90

문제 링크

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

 

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

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

programmers.co.kr

 

자바스크립트 연습 겸 프로그래머스 레벨 1 문제들을 풀어보고 있습니다.

이 문제를 C++로 풀 때는 몰랐는데 막상 풀어보니 정규표현식에 입문하기 너무 좋은 문제입니다. 이리저리 검색해보면서 정규표현식이 되게 친숙해졌습니다. 이게 복잡해 보여서 그렇지 정규식 생각보다 어렵지 않습니다..

 

우선 전체적인 코드는 이렇습니다.

function solution(new_id) {
    return new_id
        .toLowerCase()
        .replace(/[^\w-.]/g, '')
        .replace(/\.+/g, '.')
        .replace(/^\.|\.$/g, '')
    	.replace(/^$/g, 'a')
    	.substr(0, 15).replace(/\.$/g, '')
    	.replace(/^(.)$/, '$1$1$1')
    	.replace(/^(.)(.)$/, '$1$2$2');
}

 

한 단계씩 살펴보기

1) 모든 대문자를 소문자로 치환

new_id.toLowerCase()

내장 함수를 이용하면 쉽게 할 수 있습니다.

 

2) 알파벳 소문자, 숫자, 빼기, 밑줄, 마침표를 제외한 모든 문자를 제거

new_id.replace(/[^\w-.]/g, '')

정규표현식의 리터럴은 슬래시 사이에 원하는 표현식을 넣고, 끝에 플래그를 달아서 사용하면 됩니다.

플래그를 사용하지 않으면 처음으로 패턴과 일치하는 문자열을 찾고 종료하는데, g 플래그를 이용하면 패턴과 매칭 되는 모든 문자열을 찾아줍니다.

 

대괄호([])는 문자셋(Character Set)입니다. 대괄호 내에 사용한 모든 문자 중 매칭 되는 문자를 찾습니다. 하이픈(-)을 이용해 연속한 문자를 나타낼 수 있습니다.

예를 들어 대문자는 A-Z, 소문자는 a-z, 한글은 가-힣, 숫자는 0-9와 같이 사용합니다.

 

\w는 모든 영문자, 숫자, 밑줄(_)에 대응됩니다. 즉, /\w/는 /[A-Za-z0-9_]/와 동일합니다.

문자셋 내에서는 정규 표현식에서 특별한 기능을 하는 특수 문자를 일반 문자처럼 처리합니다. 따라서 아래에서 나올 \. 과 같은 이스케이프 처리를 해주지 않아도 됩니다.

 

문자셋의 처음에 ^를 붙여주면 이를 부정 문자셋(Negated Character Set)이라고 부릅니다.

부정 문자셋은 문자셋과 반대로 문자셋에 대응되는 문자를 제외한 모든 문자에 대해 대응됩니다.

 

위 코드를 해석하면 "영어 대소문자, 숫자, 밑줄(_), 빼기(-), 마침표(.)를 제외한 모든 문자를 찾아서 빈 문자열('')로 replace 해라."가 되겠습니다.

 

 

3) 연속된 마침표를 하나로 치환

new_id.replace(/\.+/g, '.')

정규표현식에서 마침표(.)는 특별한 기능을 하는 문자이기 때문에, 마침표 자체를 문자로써 매칭 시키려면 백 슬래시(\)를 이용해 마침표를 이스케이프 시켜줘야 합니다.

 

문자의 뒤에 +를 사용하면, 이는 그 문자가 한 번 이상 나왔는지에 대한 패턴을 뜻합니다.

 

위 코드를 해석하면 "마침표(.)가 한 번 이상 연속해서 나온 문자열을 '.'으로 replace 해라."가 되겠습니다.

 

 

4) 양 끝의 마침표를 제거

new_id.replace(/^\.|\.$/g, '')

^X는 문자열의 가장 앞 문자가 X와 매칭 되는지 검사합니다. 헷갈리면 안 됩니다. 이는 문자셋에서 사용된 ^와는 다른 의미입니다.

X$는 문자열의 가장 뒷 문자가 X와 매칭되는지 검사합니다.

 

|는 일반적으로 코딩할 때 사용하는 |와 비슷한 의미입니다. '또는'으로 해석하시면 되겠습니다.

 

위 코드를 해석하면 "가장 처음에 나온 마침표(.)와, 가장 뒤에 나온 마침표(.)를 빈 문자열('')로 replace 해라."가 되겠습니다.

 

 

|가 or의 의미인데 왜 코드를 해석하면 and 같은 의미가 되죠?? → 패턴에 대한 or이기 때문에 A | B 라면 A 또는 B와 대응되는 모든 문자열을 찾아준다고 생각하시면 됩니다.

 

 

5) 빈 문자열이라면, 'a'를 대입

new_id.replace(/^$/g, 'a')

^$는 4번에서 설명했습니다.

시작 문자와 끝 문자에 대응되는 문자를 써주지 않았기 때문에, 이는 곧 빈 문자열을 의미합니다.

 

위 코드를 해석하면 "new_id가 빈 문자열과 매칭 되면 'a'로 replace해라."가 되겠습니다.

 

 

6) 첫 15개의 문자만 남기고, 맨 뒤의 마침표를 제거

new_id.substr(0, 15).replace(/\.$/g, '')

자바스크립트의 substr() 함수는 시작 위치와 개수를 인자로 받습니다. 처음부터 15개의 문자만 뽑은 뒤, 4번과 같은 방식으로 맨 뒤의 마침표를 제거해줍시다.

 

 

7) 길이를 3으로 만들기

new_id.replace(/^(.)$/, '$1$1$1')
		.replace(/^(.)(.)$/, '$1$2$2');

정규표현식에서 소괄호(())는 캡쳐링 그룹(Capturing Group)이라고 합니다. 대응되는 패턴이 있을 때, 각 캡쳐링 그룹 순서대로 해당 문자열을 기억해둡니다.

이렇게 기억한 문자열을 순서대로 $1, $2, ..., $9와 같이 접근할 수 있습니다. (다만 $을 이용해 접근하는 방식은 비표준 구문이라고 합니다. 자세한 내용은 두 번째 참고사이트를 참고해주세요.)

 

마침표(.)는 어떤 문자와도 대응될 수 있습니다. 

 

따라서 위 코드를 해석하면 "문자가 하나일 땐 첫 번째 문자($1)가 세 번('$1$1$1') 나오도록, 문자가 두 개일 땐 두 번째 문자($2)가 한 번 더 나오도록('$1$2$2') replace 해라."가 되겠습니다. 

 

 

참고 링크

MDN - 정규 표현식

 

정규 표현식 - JavaScript | MDN

정규 표현식 정규 표현식은 문자열에 나타는 특정 문자 조합과 대응시키기 위해 사용되는 패턴입니다. 자바스크립트에서, 정규 표현식 또한 객체입니다.  이 패턴들은 RegExp의 exec 메소드와 tes

developer.mozilla.org

 

MDN - RegExp.$1-$9

 

RegExp.$1-$9 - JavaScript | MDN

RegExp.$1-$9 Non-standard This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior ma

developer.mozilla.org

 

728x90
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/03   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함