ioerror

[JS] 문자열 또는 숫자 배열의 내림차순, 오름차순 정렬하기 본문

JavaScript

[JS] 문자열 또는 숫자 배열의 내림차순, 오름차순 정렬하기...

반응형

자바스크립트에 내림차순 정렬이 없다고? 더구나 숫자 정렬은 엉망이라고? 

가계부를 만드는데 가장 금액이 많이 지출된 계정 순으로 정렬하고 싶다 (내림차순으로...)

그런데 자바스크립트 배열 함수에서는 내림차순이 없고, 요소가 숫자인 경우라도 문자열처럼 정렬되어 버린다.

이게 무슨 말인가 하면... 오름차순 정렬은 적은 값에서 큰값으로 정렬이 되는데 자바스크립의 sort 함수는 30원이 100원보다 많은 것처럼 [100,30] 이렇게 정렬되어 버린다.

다시말해 숫자 배열에 요소가 [2, 1, 10] 이렇게 있을 때 sort 함수를 사용하여 정렬하면 [1,10,2] 이렇게 정렬된다는 것이다.

이유는 sort 함수가 요소의 값이 숫자이든 문자열이든  아스키코드값을 기준으로 정렬을 하기 때문이다.

그냥 "2"도 문자, "10"도 문자인데 이들 첫 번째 문자의 아스키코드(16진법)가 "2"=23, "1"=22 이기 때문에 10이 2보다 앞에 온다고만 이해하자. 

 

그래서 해결 방법은?

자바스크립트의 sort 함수는 인자값을 함수로 입력할 수 있다. 정확히 말하면 비교 함수(compare function)를 입력할 수 있다.

그 비교 함수를 통해 배열에 있는 각 요소 값을 비교하여 원하는 방식으로 정렬을 할 수 있다.

 

비교함수

sort 함수의 비교 함수는 2개의 값을 받아서 3가지 경우의 값을 반환하는데 반환되는 값에 따라 2개의 값의 순서가 변경된다. 

1. 입력받은 두 개의 값이 같은 경우 : 반환 값은 0이고 순서 변경 없음

2. 첫 번째 인자 값이 큰 경우 : 반환 값은 1이고 첫번째 인자 값이 두번째 인자 값보다 커서 뒤로 이동

3. 첫번째 인자 값이 작은 경우 : 반환 값은 -1이고 첫번째 인자 값이 적기 때문에 앞으로 이동

쉽게 말해서 return A-B; 한다는 말이다.

 

코드를 보자

함수로 만들기도 하겠지만 나는 배열의 prototype으로 만들었다.

왜냐면 a라는 배열 변수를 sort 실행하고 나서 다른 b 변수에 담는다면  a와 b는 항상 동일한 배열을 가리킨다.

그래서 나중에 배열 b의 값이 변화가 있으면 a도 그대로 적용이 된다.

아래 코드의 arr_sort를 정렬을 하고 결과를 arr_sort2에 저장하면 그때부터 arr_sort와 arr_sort2는 한 몸이 되어 버리고 둘 중 어느 하나가 변경이 되면 동일하게 적용이 된다.

그리고 하는 김에 문자열 내림차순과 대소문자 구분없이 정렬 하는 함수도 추가 해보자.

/**
* 숫자 배열 오름차순 정렬
*/
Array.prototype.sort_num = function(){
  return this.sort(function(a,b){
    return a - b;
  });
}

/** 
* 숫자 배열 내림차순 정렬
*/
Array.prototype.rsort_num = function(){
  return this.sort(function(a,b){
    return b - a;
  });
}

/**
* 문자열 배열 내림차순 정렬
*/
Array.prototype.rsort_str = function(){
  return this.sort(function(a,b){
    if(a < b) return 1;
    if(a > b) return -1;
    if(a === b) return 0;
  });
}

/**
* 문자열 배열 대소문자 구분 없이 내림차순 정렬
*/
Array.prototype.rsort_istr = function(){
  return this.sort(function(a,b){
    let A = a.toUpperCase();
    let B = b.toUpperCase();
    if(A < B) return 1;
    if(A > B) return -1;
    if(A === B) return 0;
  });
}

/**
* 문자열 배열 대소문자 구분 없이 오름차순 정렬
*/
Array.prototype.sort_istr = function(){
  return this.sort(function(a,b){
    let A = a.toUpperCase();
    let B = b.toUpperCase();
    if(A < B) return -1;
    if(A > B) return 1;
    if(A === B) return 0;
  });
}
function echobr(str){
  document.write(str+"<br>");
}
let arr = [1,3,2,1,409,10,23];
arr.sort();
echobr(arr);
arr.sort_num();
echobr(arr);
arr.rsort_num();
echobr(arr);
let arr_str = ['alpha','Delta','Bravo','chalie'];
let arr_str2 = arr_str.sort();
echobr(arr_str);
echobr(arr_str2);
arr_str2.rsort_str();
echobr(arr_str);
echobr(arr_str2);
arr_str.rsort_istr();
arr_str[1] = "zulu";
echobr("arr_str : "+arr_str);
echobr("arr_str2 : "+arr_str2);

실행결과

1,1,10,2,23,3,409
1,1,2,3,10,23,409
409,23,10,3,2,1,1
Bravo,Delta,alpha,chalie
Bravo,Delta,alpha,chalie
chalie,alpha,Delta,Bravo
chalie,alpha,Delta,Bravo
arr_str : Delta,zulu,Bravo,alpha
arr_str2 : Delta,zulu,Bravo,alpha

 

 

 

반응형
Comments