sort함수를 사용해서 데이터를 정렬하는 문제를 자주 보았다.
고차함수를 활용하면 콜백함수를 문제에 맞게 정의한 후 전달할 수 있기 때문에 데이터 정렬에 편리하다는 느낌을 받았다.
[
['찬욱', 30],
['지환', 50],
['병주', 70],
['찬욱', 50],
['석준', 30],
];
이렇게 배열이 있고, 점수가 큰 순서대로 내림차순으로 정렬하고, 점수가 같으면 이름의 순서대로 오름차순으로 정렬하고 싶다.
어떻게 콜백함수를 만들어서 고차함수로 넘겨줄 수 있을까?
우선 arr.sort([compareFunction])
에서 compareFunction
은 정렬 순서를 정의하는 함수이다.
이 값이 생략이 된다면, 배열의 element들은 문자열로 취급되어 유니코드 값 순서대로 정렬된다.
이 함수는 두 개의 배열요소를 파라미터로 입력 받는다.
a,b 두개의 파라미터로 입력 받을 때, 리턴값이 0보다 작다면 a가 b보다 앞에 오도록 정렬하고, 0보다 클 경우에는 b가 a보다 앞에 오도록 정렬한다.
단, 여기서 주의할 점은 숫자 크기 순서대로 정렬하기 위해서는 sort()함수의 파라미터로 함수를 정의해야한다.
sort는 원본 배열을 변형시킨다.
그렇다면 sort를 이용해서 데이터를 정렬해보자.
먼저 점수를 비교해서 내림차순으로 정렬해야한다. 만일 점수가 같다면 이름순으로 내림차순 정렬을 해야한다.
점수를 내림차순으로 정렬하기 위해서는 scoreA-scoreB의 값을 구해서 그에 맞게 리턴값을 반환하면 된다.
scoreA-scoreB가 0보다 크다는 것은 scoreA가 scoreB보다 크다는 것이다. 큰 것이 앞으로 와야되므로 리턴값을 음수로 반환하면 된다.
scoreA-scoreB가 0보다 작다는 것은 반대로 scoreB가 scoreA보다 크다는 것이다. 큰 것을 앞으로 보내기 위해 리턴값은 양수를 반환해야한다.
그리고 점수가 같다면 이름을 마찬가지로 똑같이 비교해 오름차순 정렬을 하면된다.
function compare([nameA, scoreA], [nameB, scoreB]) {
const diff = scoreA - scoreB;
if (diff > 0) return -1;
if (diff < 0) return 1;
if (diff === 0) {
if (nameA > nameB) return 1;
if (nameA < nameB) return -1;
}
}
diff가 0보다 크다는 것은 scoreA가 scoreB보다 크다는 것이다. 그렇다면 scoreA가 scoreB보다 먼저와야하므로 음수를 리턴해야한다.
반대로 diff가 0보다 작다는 것은 scoreB가 더 크다는 것이므로 양수를 리턴해야한다.
만일 점수가 같다면 nameA와 nameB를 비교한다. nameA가 nameB보다 크다는 것은 nameB가 먼저와야되므로 양수를 리턴한다. 반대도 같은 논리가 적용된다.