[JavaScript] 문자열 내 마음대로 정렬하기

프로그래머스 코딩테스트 연습문제

문제는 문자열로 구성된 리스트를 주어진 정수 n으로, 각 문자열의 인덱스 n번째 글자를 기준으로 오름차순 정렬하기 였다.

간단한 sorting문제 인줄 알았는데, 인덱스 n의 문자가 같은 문자열이 여럿 일 경우, 사전순으로 앞선 문자열이 앞쪽에 위치합니다. 이 조건을 어떻게 처리할까가 핵심인 것 같았다.

우선 javascript에서의 sort()함수는 기본적으로 원소들을 문자열로 만든 뒤에, UTF-16 코드 유닛 값을 기준으로 순서를 정렬한다. 다시 말해 문자열로 바꾼 뒤에 정렬을 하기 때문에 숫자 정렬에 적합하지 않다.

왜 갑자기 문자열 정렬하는데 숫자 정렬에 적합하지 않냐는 얘기를 꺼냈느냐 하면, 우리는 n번째 글자를 기준으로 정렬을 하기 때문에 n번째 문자의 ASCII 코드로 비교를 하기 때문이다.

코드를 보면,

function solution(strings, n) {
    return strings.sort((a,b) => a.charCodeAt(n) - b.charCodeAt(n));
}

이렇게 첫번째 테스트 케이스는 통과 하지만 두번째 케이스는 실패한다.
n번째 글자가 같을 때, 사전순으로 앞선 문자열이 앞쪽에 위치합니다. 이 조건을 충족하지 못해서이다.

sort([callback])는 callback에 인자로 firstEl과 secondEl이 들어오며, 연산의 결과가 -1 일 때만 변경이 일어난다.

예를 들어 [a,b] 배열에서,

a - b 연산이 0보다 큰 경우 변화 x
a - b 연산이 0일 경우 변화 x
a - b 연산이 0보다 작을 경우에만 [b,a]로 swap이 된다.

내림차순으로 정렬해야 할 경우 function(a,b) => b-a 이렇게 콜백함수를 작성해주면 된다.

조건을 추가해준 코드를 보면,

function solution(strings, n) {
    return strings.sort((a,b) => {
        let first = a.charCodeAt(n); 
        let second = b.charCodeAt(n);
        
        if(first === second)
            return a.localeCompare(b);
        else 
            return first - second;
    });
}

조건을 추가하여, localeCompare함수를 사용하여 문자열끼리 비교하여 처리해주었다.

localeCompare함수는 기준 문자열과 비교했을 때 비교 대상 문자열이 정렬상 전에 오는지, 후에 오는지 혹은 같은 순서에 배치되는지를 알려주는 숫자를 리턴하는 함수다.

하지만 charCodeAt함수나 localeCompare함수 때문인지 처리시간이 길게 나오는 경우가 있어서 좋은 코드를 참고하여 수정해봤다.

function solution(strings, n) {
    return strings.sort((a,b) => {
        const first = a[n];
        const second = b[n];
        
        if(first === second)
            return (a > b) - (a < b);
        else
            return (first > second) - (first < second);
    });
}

이렇게 비교를 먼저해서 나온 bool을 연산하여 정렬했다. (true = 1, false = 0)

다른 사람의 풀이를 보다가 참고할만한 코드가 있어서 첨부한다.

function solution(strings, n) {
    return strings.sort().sort((a,b) => a.charCodeAt(n)-b.charCodeAt(n));
}

먼저 문자열 배열을 sort해서 두번째 조건 먼저 처리하고, 특정 문자 조건을 처리해줬다.


* 참고

좋은 웹페이지 즐겨찾기