https://programmers.co.kr/learn/courses/30/lessons/17686
function solution(files) {
files = files.map(x => {
x = x.replace(/([0-9])/, ".$1");
x = x.split('.');
return x;
})
files.sort((a, b) => {
var aHead = a[0].toLowerCase();
var bHead = b[0].toLowerCase();
if(a === b){
return 0;
}
if (aHead === bHead) {
var aNum = parseInt(a[1]);
var bNum = parseInt(b[1]);
if(aNum === bNum) return 0;
return aNum - bNum;
}
return aHead < bHead ? -1 : aHead > bHead ? 1 : 0;
})
files = files.map(x => {
x = x.join(".");
x = x.replace(/([.])/, "");
return x;
})
return files;
}
문제에서 주어진 진행과정을 충실히 구현하는 구현문제이다.
- 파일명은 우선 HEAD 부분을 기준으로 사전 순으로 정렬한다. 이때, 문자열 비교 시 대소문자 구분을 하지 않는다. MUZI와 muzi, MuZi는 정렬 시에 같은 순서로 취급된다.
- 파일명의 HEAD 부분이 대소문자 차이 외에는 같을 경우, NUMBER의 숫자 순으로 정렬한다. 9 < 10 < 0011 < 012 < 13 < 014 순으로 정렬된다. 숫자 앞의 0은 무시되며, 012와 12는 정렬 시에 같은 같은 값으로 처리된다.
- 두 파일의 HEAD 부분과, NUMBER의 숫자도 같을 경우, 원래 입력에 주어진 순서를 유지한다. MUZI01.zip과 muzi1.png가 입력으로 들어오면, 정렬 후에도 입력 시 주어진 두 파일의 순서가 바뀌어서는 안 된다.
위 세과정에서 입력은 문자열배열로 주어지며 배열의 안의 원소인 문자열을 하나씩 가공하는 과정을 거쳐야한다.
문자열을 가공하는 방식에서 정규식을 사용한다.
.
를 삽입하기로 한다. 이유는 TAIL과 NUMBER의 구분점이 .
이기 때문이다.x.replace((/[0-9])/,'.$1');
해당 코드는 정규식을 바탕으로 문자열 찾아낸다음 해당 문자열로 교체한다는 뜻이다.
여기서 'img01.png'
는 img.01.png
로 변환되고 x.split('.')
에 의해서 세개의 구분으로 나뉘게 된다.
이제 HEAD 부분을 toLowerCase()
혹은 toUpperCase()
등으로 전부 소문자 혹은 대문자로 바꾼다음에 문자열 비교를 통해서 사전식 정렬을 한다. HEAD가 비교순위가 같아서 가릴수 없을때는 NUMBER 비교를 한다.
NUMBER은 parseInt()
를 통해서 비교를 한다. 비교순위가 같다면 return 0
을 함으로서 비교 순서를 유지한다.
정규식 :
/
, /
두 슬래쉬 안으로 정의된 형태를 말한다. (형태)
라는 것은 캡쳐할 문자열로서 해당 문자열을 찾아내서 $1
등으로 사용하면 캡쳐한 문자열이 참조된다. [0-9]
는 모든 숫자를 말한다. 따로 맨끝에 플래그가 없다면 가장 먼저 나오는 숫자를 대상을 찾아서 반환한다.
sort()
함수 :
정렬규칙이 숫자로서 오름차순 이라면 return a-b
정렬규칙이 문자열로서 사전식이라면 a > b ? 1 : a < b ? -1 : 0
parseInt()
함수와 Number()
함수의 차이 :
parseInt()
는 변환할 문자열이 숫자로 시작하면 시작부터 숫자인 부분만 숫자로 변경해서 반환한다. Number()
는 문자열 자체가 숫자말고 다른문자가 있다면 변환할수 없다고 판단해서 NaN (Not a Number)
값을 반환한다.