-
[CodeKata] 프로그래머스 : 4.20(화), 파일명 정렬Algorithm 2021. 4. 20. 17:54반응형
🥋 Ooooth!! (Level 2)
파일명들의 배열을 재정렬하면 된다. 먼저 나누는 방법은 가운데 숫자(최대 5자리) 기준으로 Head, Number, Tail 세 부분이다.
정렬방법은 1) Head 사전순, 2) Number 숫자비교(0제외), 3) 인덱스 순이다. 즉, Tail은 필요가 없을 것이다.
🧮 풀이
function solution(files) { const regex = /^[0-9]*$/ let fileInfos = []; files.forEach(file => { const fileStrs = file.split("") const idx1 = fileStrs.findIndex(s => regex.test(s)); let idx2; for (let i = idx1+1 ; i < idx1+6 ; i++) { idx2 = i; if (i > file.length || !regex.test(file[i])) break; } fileInfos.push([ file.slice(0,idx1), file.slice(idx1, idx2), file.slice(idx2), ]) }) fileInfos.sort((a,b) => { if (a[0].toUpperCase() < b[0].toUpperCase()) return -1; else if (a[0].toUpperCase() > b[0].toUpperCase()) return 1; else { if (Number(a[1]) < Number(b[1])) return -1; else if (Number(a[1]) > Number(b[1])) return 1; else return fileInfos.indexOf(a) < fileInfos.indexOf(b) ? -1 : 1; } }) return fileInfos.map(file => file.join("")) }
- 파일명 분할
- files를 [head, number, tail] 2차원 배열로 이루어진 fileInfos 배열로 재가공하였다. regex는 숫자를 확인하기 위한 정규식이다.
- files를 forEach를 통해 순회한다. 먼저, 각 file에 findIndex() 메서드 적용을 위해 split() 하여 배열로 만들어준다.
- idx1은 head, number를 구분하는 인덱스이다. 숫자가 시작되는 인덱스를 findIndex() 메서드로 찾아준다.
- idx2는 number, tail을 구분하는 인덱스이다. idx1보다 커야하며, 최대 5자리이므로 (idx1 + 6) 전까지만 고려하는 것이다.
- 중간에 file.length 길이를 초과하거나 숫자가 아닌 부분을 만난다면 break 처리한다. number가 더 이상 길어질 필요가 없다.
- 이렇게, idx1, idx2로 각각 slice를 해주면 [head, number, tail] 로 분할할 수 있다.
- 파일명 정렬
- sort() 메서드를 통해 정렬한다. -1인 경우 앞으로, 1일 경우 뒤로 배치된다.
- 먼저, head(0번째 요소)를 비교한다. 이 때, 대소문자는 고려하지 않으므로 toUpperCase() 로 통일하여 비교한다.
- 만약 같다면(else), number(1번째 요소)를 비교한다. 이 때, 앞의 000 등을 제거한 숫자로 비교하기 위해 Number() 를 적용한다.
- 여기서도 둘이 같다면(else), 두 요소(a,b)의 fileInfos 인덱스에 따라 정렬한다. fileInfos의 순서가 곧 files에서 순서와 동일.
- 이렇게 정렬된 fileInfos의 각 요소를 다시 join() 시켜주면 본래의 files에서 파일명 형태로 돌아온다. 이를 최종 반환한다.
🖇 리뷰
function solution(files) { let answerWrap = files.map((file, index) => ({file, index})); const compare = (a, b) => { const reg = /(\D*)([0-9]*)/i; const A = a.match(reg); const B = b.match(reg); const compareHead = A[1].toLowerCase().localeCompare(B[1].toLowerCase()); const compareNumber = (a, b) => { return parseInt(a) > parseInt(b) ? 1 : parseInt(a) < parseInt(b) ? -1 : 0 } return compareHead === 0 ? compareNumber(A[2], B[2]) : compareHead } answerWrap.sort((a, b) => { const result = compare(a.file, b.file); return result === 0 ? a.index - b.index : result; }) return answerWrap.map(answer => answer.file); }
compare() 라고 하는 head, number를 비교하는 함수를 만들어줬다. 먼저, match() 와 정규식을 통해 각 file 파일명을 나눠준 모습이다.
compareHead는 localeCompare() 메서드를 통해 두 문자를 비교하며, 둘이 같으면 0을 반환하게 된다.
compareNumber는 parseInt를 통해 숫자 부분을 비교한다. 둘 역시 같으면 0을 반환하게 되고, 이것이 result에 반영되어 index 비교로 넘어가게 되는 것이다.
localeCompare() 라는 새로운 메서드와, match() + 정규식 조합의 새로운 활용법을 알게 되었다!
드디어, 프로그래머스 2단계도 1개 문제만 남겨두고 있다. 요즘 취업준비로 알고리즘을 2주씩이나 올리지 못한것으로 보였다.
못다 정리한 프론트 개념과, 면접에서 부족하다고 느꼈던 Web 지식이나 React 개념을 빨리 포스팅하고,
알고리즘도 얼른 3단계로 넘어가고 싶은 마음이다!
반응형'Algorithm' 카테고리의 다른 글
[CodeKata] 프로그래머스 : 4.28(수), 추석 트래픽 (0) 2021.04.28 [CodeKata] 프로그래머스 : 4.21(수), n진수 게임 (0) 2021.04.21 [CodeKata] 프로그래머스 : 4.7(수), 압축 (0) 2021.04.08 [CodeKata] 프로그래머스: 4.1(목), 방금그곡 (0) 2021.04.03 [CodeKata] 프로그래머스: 3.29(월), 후보키 / [이론] 비트 연산자 (0) 2021.03.29