Javascript Sort 컴팩트 가이드 | 정렬 | protect-me

protect-me·2021년 5월 12일
6

Javascript + Algorithm

목록 보기
4/8
post-thumbnail

javascript의 sort에 대해 알아보자. Array.sort()


용어 정리

오름차순 : 진행할수록 올라감 ex) 1, 2, 3, 4, 5, ...
내림차순 : 진행할수록 내려감 ex) 7, 6, 5, 6, 3, ...
*진행 방향 : 좌 ➤ 우 OR 상 ➤ 하



기본 개념

Array.sort()는 "배열" 의 요소를 정렬한 후 반환함.

const example = [3, 2, 5, 1, 4];
example.sort();
console.log(example.sort()); // [1, 2, 3, 4, 5]


주의 사항 🚨

원본 수정

sort 함수를 사용하면 원본이 수정됨에 주의.
다시 한 번 강조함.
복사본이 만들어지는 것이 아님.

따라서 원본 수정을 원치 않을 경우,
간단하게는 slice를 통해 얕은 복사한 후 사용.

const example = [3, 2, 5, 1, 4];
const sortedExample = example.sort();
console.log(sortedExample); // [1, 2, 3, 4, 5]
console.log(example); // [1, 2, 3, 4, 5] - 원본도 수정되어 있음

유니코드 기준

정렬은 stable sort가 아닐 수 있음.
기본 정렬 순서는 "문자열""유니코드" 코드 포인트를 따름.

example = [5, 3, 2, 1, 10];
example.sort();
console.log(example); // [1, 10, 2, 3, 5]

우리가 기대한 [1, 2, 3, 5, 10]과는 다르게 [1, 10, 2, 3, 5]를 반환
💡 인자를 "문자열로 변환" 후 "유니코드"로 비교하기 때문

const months = ["March", "Jan", "Feb", "Dec"];
months.sort();
console.log(months); // ["Dec", "Feb", "Jan", "March"] - 문자열 첫글자의 유니코드 순(알파벳 순)

stable sort를 위해서는 아래에서 다루는 compareFunction을 설정해야함.



비교 함수(compareFunction)

sort 함수 내부에 비교 함수를 작성하여 원하는 조건으로 정렬할 수 있음.

const arr = [5, 3, 2, 1, 10];


// 비교함수 : 오름차순 정렬 (ASC)
arr.sort((a, b) => {
  return a - b;
});
console.log("ASC1 : ", arr); // [1, 2, 3, 5, 10]

arr.sort((a, b) => {
  if (a > b) return 1;
  if (a < b) return -1;
  return 0;
});
console.log("ASC2 : ", arr); // [1, 2, 3, 5, 10]



// 비교함수 : 내림차순 정렬 (DESC)
arr.sort((a, b) => {
  return b - a;
});
console.log("DESC1 : ", arr); // [10, 5, 3, 2, 1]

arr.sort((a, b) => {
  if (a > b) return -1;
  if (a < b) return 1;
  return 0;
});
console.log("DESC2 : ", arr); // [10, 5, 3, 2, 1]

위 로직에서 유추해보자면,
String type으로 변환되지 않고 기존의 Number type으로 비교가 되었으며
두 값을 비교해서 return하는 값이 양수인지, 음수인지에 따라 다르게 정렬됨을 알 수 있음.



비교 함수 - 개념 설명

const arr = [5, 3, 2, 1, 10];

// 비교함수 : 오름차순 정렬 (ASC)
arr.sort((a, b) => {
  return a - b;
});
console.log("ASC1 : ", arr); // [1, 2, 3, 5, 10]
  1. [5, 3]을 비교 함수에 "역순"으로 전달 🚨
  2. a = 3, b = 5
  3. return a - b = return 3 - 5 = return -2
  4. return 값이 음수이므로 둘의 위치를 변경(0 또는 양수일 경우 continue)
  5. 변경된 배열 : [3, 5, 2, 1, 10]
    ... 반복

위와 같은 방식으로 반복하여 오름차순으로 정렬.

정리 : 앞/뒤 값을 역순으로 넣고 비교해서
return 값을 음수로 하면 자리를 바꾸고 그렇지 않으면 그대로 둠.



다중 조건 정렬(Multi-Sort)

비교 함수에 조건을 추가해서 다중 조건으로 정렬이 가능함.

// 번호, 몸무게, 승률, 우승횟수
const list = [
  [1, 60, 33.333333, 3],
  [2, 80, 33.333333, 1],
  [3, 60, 66.666666, 3],
  [4, 80, 66.666666, 2],
  [5, 70, 66.666666, 2],
  [6, 70, 66.666666, 2],
];

// 정렬 : 승률 높은 순 > 우승횟수 높은 순 > 몸무게 높은순 > 번호 낮은 순
list.sort((a, b) => {
  let numA = a[0];
  let numB = b[0];
  let weightA = a[1];
  let weightB = b[1];
  let rateA = a[2];
  let rateB = b[2];
  let countA = a[3];
  let countB = b[3];

  if (rateA > rateB) return -1;
  if (rateA < rateB) return 1;
  if (countA > countB) return -1;
  if (countA < countB) return 1;
  if (weightA > weightB) return -1;
  if (weightA < weightB) return 1;
  if (numA > numB) return 1;
  if (numA < numB) return -1;
  return 0;
});
console.log(list);
// 0: [3, 60, 66.666666, 3]
// 1: [4, 80, 66.666666, 2]
// 2: [5, 70, 66.666666, 2]
// 3: [6, 70, 66.666666, 2]
// 4: [1, 60, 33.333333, 3]
// 5: [2, 80, 33.333333, 1]

💡 추가 설명
1. a, b는 역순으로 할당되기 때문에 a = 뒤 값, b = 앞 값 이라는 것에 주의
2. return 값이 음수이면 둘의 자리를 바꿈

if (rateA > rateB) return -1; // rateA(뒤)가 rateB(앞) 보다 클 경우 교체
if (rateA < rateB) return 1; // rateA(뒤)가 rateB(앞) 보다 작을 경우 그대로 둠.
  // 뒤가 앞보다 클 경우에만 자리를 바꿨으므로 최종적으로 앞이 크게 됨 = 내림차순
if (countA > countB) return -1;
if (countA < countB) return 1;
  // 위와 동일
if (weightA > weightB) return -1;
if (weightA < weightB) return 1;
  // 위와 동일
if (numA > numB) return 1; // numA(뒤)가 numB(앞)보다 클 경우 그대로 둠.
if (numA < numB) return -1;// numA(뒤)가 numB(앞)보다 작을 경우 교체.
  // 뒤가 앞보다 작을 경우에만 자리를 바꿨으므로 최정적으로 앞이 작게 됨 = 오름차순


객체 정렬

var items = [
  { name: 'Edward', value: 21 },
  { name: 'Sharpe', value: 37 },
  { name: 'And', value: 45 },
  { name: 'The', value: -12 },
  { name: 'Magnetic', value: 13 },
  { name: 'Zeros', value: 37 }
];


// value 기준으로 정렬
items.sort((a, b) => a.value - b.value);

// name 기준으로 정렬
items.sort((a, b) => {
  var nameA = a.name.toUpperCase(); // ignore upper and lowercase
  var nameB = b.name.toUpperCase(); // ignore upper and lowercase
  if (nameA < nameB) return -1;
  if (nameA > nameB) return 1;
  return 0; // 이름이 같을 경우
});

// name 기준으로 정렬 축약 (upper, lower 판단 필요)
items.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);






  • 2021.05.12 - 최초 작성

  • 댓글 환영 질문 환영 by.protect-me

profile
protect me from what i want

0개의 댓글