[JS/Programmers] 17686. [3차] 파일명 정렬

정나린·2023년 3월 13일
1

💬 문제

문제 난이도: Programmers Lv.2

문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/17686

❗️접근방법

문자열 파싱 + 정렬
정규 표현식을 사용하면 빨리 풀 수 있겠다.

👆 1차 코드(통과❌)

function solution(files) {
    const obj = {};
    for (let i = 0 ; i < files.length; i+=1){
        const file = files[i].toUpperCase();
        let head = '';
        let number = '';

        for (let j = 0; j < file.length; j+=1){
            if (isNaN(file[j])){
                if (!number) head += file[j];
                else break;
            }else {
                console.log('number:', file[j])
                number += file[j];
            }
        }

        if (obj.hasOwnProperty(head)){
            obj[head].push([number, i]);
        }else{
            obj[head] =[[number, i]];
        }
    }
    console.log(obj)
    const keys = Object.keys(obj).sort();
    const arr = [];
    for (let i = 0; i < keys.length; i+=1){
        const valueArr = obj[keys[i]].sort((a, b)=>a[0]-b[0]);

        for (let j = 0; j < valueArr.length; j+=1){
            const index = valueArr[j][1];
            arr.push(files[index]);
        }
    }
    return arr;
    
}

✌️ 2차 코드(통과✅)

function solution(files) {
    const obj = {};
    for (let i = 0 ; i < files.length; i+=1){
        const file = files[i].toUpperCase();
        let head = '';
        let number = '';

        for (let j = 0; j < file.length; j+=1){
            if (isNaN(file[j]) || file[j] === ' '){
                if (!number) head += file[j];
                else break;
            }else number += file[j];
        }

        if (obj.hasOwnProperty(head)){
            obj[head].push([number, i]);
        }else{
            obj[head] =[[number, i]];
        }
    }
    const keys = Object.keys(obj).sort();
    const arr = [];
    for (let i = 0; i < keys.length; i+=1){
        const valueArr = obj[keys[i]].sort((a, b)=>a[0]-b[0]);

        for (let j = 0; j < valueArr.length; j+=1){
            const index = valueArr[j][1];
            arr.push(files[index]);
        }
    }
    return arr;
    
}

isNaN(''), isNaN(' ')
빈 문자열, 공백 같은 falsy한 값을 isNaN의 인자로 넘기면 false가 반환된다.
따라서 이 문제의 경우 공백 문자 처리를 따로 해야 한다.
cf. isNaN(true), isNaN(false) -> false (1, 0으로 인식되므로)

🤟 3차 코드 (정규표현식 사용한 다른 사람 풀이 참고)

function solution(files){
	return files.sort((a, b)=>{
		const headerA = a.match(/^\D+/)[0].toLowerCase();
		const headerB = b.match(/^\D+/)[0].toLowerCase();
		
		if(headerA < headerB) return -1;
		if(headerA > headerB) return 1;
		
		const numberA = a.match(/\d+/)[0].replace(/^0+/, '');
		const numberB = b.match(/\d+/)[0].replace(/^0+/, '');
		
		return numberA - numberB;
	});
}

✍️ 이 문제에서 사용된 정규 표현식

  1. head를 기준으로 대소문자 구분 없이 사전 순으로 정렬
  2. head가 같다면, number를 기준으로 숫자 순으로 정렬(이때 맨 앞의 0은 무시)
  3. 2까지 동일하다면 입력 순으로 정렬

HEAD: 시작부터 숫자가 나오기 전까지의 문자열
match(/^\D+/)
→ ^: 입력 시작 부분에 대응
→ /D: 숫자가 아닌 문자에 대응
→ +: 앞의 표현식이 1회 이상 연속으로 반복되는 부분에 대응

NUMBER: HEAD 다음에 나오는 연속된 숫자들
match(/\d+/)
→ \d: 숫자에 대응
→ +: 앞의 표현식이 1회 이상 연속으로 반복되는 부분에 대응
replace(/^0+/, ‘’)을 통해 앞의 0을 지워줌.
numberA와 numberB까지 같을 경우에 0을 반환하므로 입력 순으로 정렬된다.

(참고: https://after-newmoon.tistory.com/82)

0개의 댓글