본문 바로가기
컴퓨터 사이언스/TIL 정리

[프론트엔드][자바스크립트] TIL Day-19.1 Sort( )함수 및 동작원리, 곁들여 Return값 a - b 완벽 이해해보기

by 메리뉴데이 2022. 4. 21.

 

<web docs 발췌>

 

MDN Web Docs를 보며, 다른 자료들을 참조하며 이해해나간 내용을 정리한다.

sort( ) 메서드는 배열의 요소들을 정렬하여 반환한다.

다만, 그 정렬은 기본적으로 문자열의 유니코드 순서를 따르므로, 특별히 수를 정렬할 때 우리가 생각하는 숫자의 크기 순서대로 정렬되지 않는다. 다음 콘솔 박스를 보면 숫자들의 배열을 그냥 sort( ) 메서드를 적용하면 다음과 같이 정렬됨을 알 수 있다. 이것이 바로, 숫자의 크기대로 정렬되지 않고 숫자가 문자열로 변환되어 문자열의 유니코드 순서를 따라 정렬되는 것이다. 살펴보면 맨 앞자리의 숫자가 기준이 된 뒤, 그 뒤에 digit이 늘어나는 것을 앞자리 숫자(0, 1, 2, ...) 의 하위 문자열로 인식하여 정렬해놓은 것을 볼 수 있다.

 

<관련 내용 실행 결과 화면>




그래서, 정렬 순서를 정의하는 비교함수(아래 소스에서는 function이라는 이름으로 지정)를 사용하여 수를 문자열 변환 후 정렬되는 것을 막고 숫자들의 크기로 비교하여 제대로 된 수 정렬을 얻을 수 있다.
이때, 비교함수를 사용하게 되면 배열 요소들은 비교함수의 반환 값(return 값)에 따라 정렬을 하게 된다.

 

<관련 내용 실행 결과 화면>

 

위의 실행화면을 보면 알 수 있듯이, sort( ) 메서드에 function이라는 비교함수를 콜백함수로 넣어주고 실행해보면
매개변수를 a, b로 지정한 것이
두 숫자를 한 쌍으로 첫번째 인자인 a에는 두번째의 숫자가, 그리고 두번째 인자인 b에는 첫 번째의 숫자가 들어가 쌍을 이루는 것을 볼 수 있다.
즉, 인자 한 쌍(a, b)에 배열요소가 순차적으로 대입되는 것이 아니라 (뒤의 것, 앞의 것)의 순서쌍으로 묶인다는 사실이다.

그리하여, 위의 배열 같은 경우, (5, 100), (30, 5), (10, 30), (22, 10), (55, 22), (72, 55), (46, 72), (0, 46), (12, 0), (68, 12)로 쌍을 이룸을 왼쪽 박스 console log에서 확인할 수 있다.

 

 

 

 

 

 이제 잠시 return 값의 의미에 대해서 알아보자.

 위의 실행화면에서 return 값으로 1을 주면, 주황 점선 사각형과 같이 원래의 배열의 전체가 순서대로 보여진다.

 

 

반면, return 값으로 -1을 주면 주황 점선 사각형과 같이 원래의 배열 순서의 역순으로 전체 배열이 보여지는 것을 알 수 있다.

그럼 return 값으로 0을 주면?

 

 

return 값이 0일 때에는 return 값이 1일 때와 동일하게 똑같은 순서로 보여짐을 알 수 있다.

그럼 return 값이 꼭 1, -1 일 경우에만이냐? 나만 궁금하니?


그렇다. 이 때의 1과 -1은 꼭 그 값으로서의 의미를 가지는 것이 아니라, 리턴값으로 양수가 나왔느냐, 음수가 나왔느냐의 의미에서 대표적으로 쓰인 수일 뿐이다. 그렇다면 실험 한번 해보고 싶어지지 않는가? 넣어보시길. 100도 좋고 -3도 좋다.

실행결과를 확인해보고 나면,
전체 배열로 볼 때, return 값의 의미는 양수(or 0)일 때 정순, 음수일 때 역순 이라는 점을 알게 될 것이다.

이걸 순서쌍으로 한정지어 볼 때는, 리턴값이 양수(or 0)일 때 두 개의 데이터로 묶인 쌍이 서로 자리를 바꾸지 않고 그 모양을 유지하고(배열전체 기준으로 할 때는 원 배열의 정순), 리턴값이 음수일 때는, 두 개의 데이터 쌍이 서로의 자리를 바꾼다(배열전체 기준으로 할 때는 기준으로 원배열의 역순)는 사실이다.

현재는 sort( ) 메서드, 즉 정렬과 상관없이 리턴값의 의미와 그것의 작용 결과를 살펴본 것이다. 

정렬은 이 리턴값을 통해 작동하고 있기 때문에, 이 리턴값 자체의 작동 원리를 알면 오름차순 정렬과 내림차순 정렬의 매커니즘을 깨닫게 되는데, 한걸음 내딛게 되는 것이다.

 

 자, 다시 읽고 있던 MDN Web Docs를 보면, 다음과 같은 설명이 나온다.

 

     

' 문자열 대신 숫자를 비교하기 위해 도입된 비교함수는 a와 b를 순서쌍으로 매개변수로서 이용한다.

이런뒤 return값을 a - b로 주게 되면, 오름차순으로 정렬하는게 된다.' ???

 

흠.. 이게 밑도 끝도 없어보이는 소리인고..

과정과 이해는 생략하고 결론만 턱 하니 내놨다.

수많이 해보았던 경험상 대충 넘어가면 머리에 남지도 않고, 이해도 안되고 해서

한참을 고민하고 퍼즐맞추듯이 머리 속의 개념 파편들을 정리하고 모아본다.                 \

 

 

                     

 

 

(내 소스코드 기준한 naming) 비교함수 function(a, b)는 console에서 직접 실습해 로그값을 확인해봤듯이

실제 배열 데이터의 쌍(a, b)은 (뒷 수, 앞 수)로 이루어진 것을 눈으로 확인할 수 있었다.   

    ... 사족으로 수학 메서드 정리하면서 인자 숫자1과 숫자2가 적용되어 들어갈 때

                  숫자2와 숫자1로 들어간 메서드를 본거 같기도 하고,

                          이런 현상에는 더 깊은 뭔가의 이해가 선행되야 하는 부분이 있기도 한 것 같고..

                                                                                                    추후에 여력되면 자세히 살펴보고 공부해보는 걸로.

 

 

 

 

비교함수의 두 인자 a와 b는 뒷 수와 앞 수의 쌍이고 비교하여(차이를 구하여 a 빼기 b, 뒷수 빼기 앞수) 나온 값(return값이 된다)이 양수(or 0)이면 (그 값은 1이든 100이든 순서쌍마다 다르겠지?) 그 데이터는 자리 변화없이 정순으로 가고(리턴값의 의미를 위에서 설명) a - b가 음수가 나오면 리턴값이 음수라는 이야기이고, 그럼 역순으로 자리바꿈이 일어난다. 이 때, 음수의 의미는 b가 a보다 크다는 의미이며, 앞 수가 뒷 수보다 크다는 의미이다. 이때 리턴값이 음수인 관계로 그 둘은 자리를 바꾸게 되고, 큰 수인 b인 앞 수가 자리를 바꿔 뒤로 가고, 작은 수인 a인 뒷 수가 앞으로 가게 되면서  이런 과정이 모든 쌍에 적용이 된 뒤에는 종국에,  큰 수가 뒤로 가고, 작은 수가 앞으로 오는 오름차순의 모양으로 정렬이 되는 것이다.

 

 쉽사리 이해를 못하는 부분들이기도 해서 내림차순을 의미한다고 작성하는 return b - a; 로 다시금 설명을 해보자면,

b(앞 수) - a(뒷 수)가 양수(or 0)이면 앞 수인 b가 뒷 수인 a보다 큰 상황이고, 리턴값이 양수이어서 자리바꿈이 없어 큰 수인 b(앞 수)와 작은 수인 a(뒷 수)가 자리를 바꾸지 않고 그대로 유지하게 된다. 또 b - a가 음수가 나오면 리턴값이 음수라는 이야기이고, 그럼 역순으로 자리바꿈이 일어난다. 이 때, 뒷 수인 a가 앞 수인 b보다 크다는 의미이며, 리턴값이 음수이므로 이 두 수는 자리를 바꾸게 된다. 그래서 큰 뒷 수 a와 작은 앞 수 b가 자리를 바꿔 , 큰 수인 뒷 수 a가 앞으로 오고, 작은 수인 앞수 b가 뒤로 가게 된다. 이런 과정이 모든 쌍에 적용이 된 뒤에는 종국에,  큰 수가 앞으로 가고, 작은 수가 뒤로 오는 내림차순의 모양으로 정렬이 되는 것이다. 

 

 

 

다시 설명하면 리턴값은 비교했던 그 두수 중 어떤게 더 큰지 작은지와는 상관없이 그저 리턴값으로 주어진 값이 음수이면 자리바꿈이 일어나는 것이다. 

이때, a - b 뒷 수에서 앞 수를 빼기에서는 리턴값이 음수가 나오려면 앞 수가 크고, 뒷 수는 작아야하고 이런 경우에는 자리바꿈이 일어나 작은 뒷 수가 앞으로 오고 큰 앞 수가 뒤로 가게 되어 오름차순 정렬이 되고, 

b - a 앞 수에서 뒷 수를 빼기에서는 리턴값이 음수가 나오려면 뒷 수가 크고, 앞 수는 작아야하고 이런 경우에는 자리바꿈이 일어나 큰 뒷 수가 앞으로 오고 작은 앞 수가 뒤로 가게 되어 오름차순 정렬이 이루어지게 되는 것이다.

 

헉헉... 그 긴 장정이 이제야 마무리되는 이 느낌 

 

 

비교함수에서 무엇이 a이고 무엇이 b가 되느냐 명확한 공표가 없어 혼동이 왔지만, 

직접 실행해보고 차근차근히 풀어나가보니 처음 정리했던 a, 뒷 데이터, b, 앞 데이터라는 전제가 맞아야 
 return값으로 설정하는 a - b가 오름차순으로 정렬하라, b - a가 내림차순 정렬하라는 뜻이다가 성립하게 되는 것으로 정리할 수 있었다.

 

 

 

a(뒷 수) - b(앞 수)
; a(뒷 수)에서 b(앞 수)를 빼서 양수(or 0)가 나오면(뒷 수가 크고, 앞 수가 작은 상황) 그대로 두고, 
a(뒷 수) - b(앞 수)가 음수가 나오면(이 때는, 뒷 수가 작고 앞 수가 큰 상황) 자리를 바꾸게 된다(그래서 큰 수가 뒤로 가게 되고 작은 수가 앞으로 오게 됨). 이런 식으로 나머지 쌍들도 계속 자리를 바꾸게 되면 전체 배열은 오름차순으로 정렬되게 된다.


b(앞 수) - a(뒷 수)
; b(앞 수)에서 a(뒷 수)를 빼서 양수(or 0)가 나오면(앞 수가 크고, 뒷 수가 작은 상황) 그대로 두고, 
a(뒷 수) - b(앞 수)가 음수가 나오면(이 때는, 앞 수가 작고 뒷 수가 큰 상황) 자리를 바꾸게 된다(그래서 큰 수가 앞으로 가게 되고 작은 수가 뒤로 오게 됨). 이런 식으로 나머지 쌍들도 계속 자리를 바꾸게 되면 전체 배열은 내림차순으로 정렬되게 된다.