개발공부

sort 배열 문법

아리단길아조씨 2024. 1. 9. 00:24
728x90


- 기본 문법
ex) arr.sort([비교함수]) 
* 비교함수는 옵션임(넣어도 그만 안넣어도 그만)

sort가 뭔데...?
1. 배열을 정렬할 때 사용하는 친구임.
2. 정렬이 된 배열을 반환한다.

sort의 기본적인 특징
1. 정렬이 된 배열을 반환한다.(함정 주의) => *  비교 함수의 중요성 *
2. 배열 그 자체가 변환이 된다

// 정렬된 배열도 쓰고, 오리지널 배열도 그래도 유지하고 싶다.

// 1. 문제의 배열 등장
    let originalArray = [3, 1, 4, 1, 5, 9];
// 2. originalArray를 복사를 시도한다.
    let sortedArray = originalArray;
// 3. 복사를 시도한 배열을 정렬한다.
    sortedArray.sort();

// 4. 정렬이 됐는지 콘솔로 originalArray와 sortedArray를 찍어본다.
    console.log(originalArray);
    console.log(sortedArray);

결과는 절망스럽게도
Sorted Array: [1, 1, 3, 4, 5, 9] Original Array: [1, 1, 3, 4, 5, 9] 라고 알려준다.

그렇다면 정녕 방법은 없는가? ㄴㄴ... 제대로 복사를 하자

솔루션 1. slice를 사용해서 배열을 복사해서(잘라와서) sort(정렬)를 해준다.

// 배열 복사 솔루션
// 솔루션 1. slice를 사용해서 배열을 복사해서(잘라와서) sort(정렬)를 해준다.

   let sliceAndSortedArr = originalArray.slice().sort();
// 콘솔 함 찍어봅시다.... 결과를 확인해보면 orgin배열은 멀쩡히 살아있으면서
// sliceAndSortedArr 임마는 성공적으로 복사가 된 후, 정렬이 된 것을 확인 가능하다.
    console.log(originalArray);
    console.log(sliceAndSortedArr);
    [ 3, 1, 4, 1, 5, 9 ]
    [ 1, 1, 3, 4, 5, 9 ]

솔루션2. [...arr] 스프레드 연산자를 사용하여 복사 한 후 sort를 해준다.

let spreadAndSortedArr = [...originalArray].sort();
// 콘솔 함 찍어보자
console.log(originalArray); // 원래 배열
console.log(spreadAndSortedArr); // 스프레드 연산자로 복사를 한 후 정렬한 배열
[ 3, 1, 4, 1, 5, 9 ]
[ 1, 1, 3, 4, 5, 9 ]


sort 문법의 기본 원리

arr.sort([비교함수]); 가 기본적인 모양인데 비교함수를 넣을 수 있는 자리가 옵션으로 마련이 되어있다.
비교함수 자리에 옵션이라고 비교함수를 넣지 않는다..?
let arr = [2, 1, 9, 80]; 이라는 변수가 있다고 가정을 해본다.

arr.sort()를 통해서 정렬을 하면?? 
[1, 2, 9, 80]을 생각하겠지만 응~ 아니야~ 뜬금없이 [1, 2, 80, 9] 가 나온다.(???)
sort();는 문자열로 변환을 하고 오름차순으로 유니코드의 순서대로 정렬을 하게 되는데
여기에서 비교 함수의 중요성이 보이게 된다..

 * 오름차순(asc = 어센딩)으로 정렬하기 * 
=> arr.sort((a, b) => a - b); === arr.sort(fuction(a, b) {return a - b});

 * 내림차순(desc = 디센딩)으로 정렬하기 * 
=> arr.sort((a, b) => b - a); === arr.sort(function(a, b) { return a - b});

이유는 하단을 참고합시다.

- a와 b를 뺐을 때 결과가 음수가 나오면 a와 b의 위치는 바뀌고, 양수가 나오면 변하지 않는다. 
 * 왜 인덱스 1, 2에서 a와 b의 위치가 바뀌었는가?? : JS가 채택한 알고리즘 방식이기 때문에 만든 사람한테 따져야할 듯


  * 객체로 이루어진 배열에서의 정렬 *
귀찮다. VS에 열심히 써가면서 했으니까 나중에 읽을 때도 이해되겠지 뭐...

- 비교함수 안의 obj1, obj2는 각각의 객체 1개씩을 의미한다.
- return문에서 obj2.age - obj1.age 한 값을 반환한다.
--> obj2, obj1의 age key에 접근해서 value(값)을 내놓으라고 협박한다. 

그 이후는 비스무리한 내용들임 천천히 코드 읽으면서 되새김질을 하면 될듯.

let items = [
    { name: "Edward", age: 21 }, ----------> obj.1
    { name: "Sharpe", age: 37 }, ----------> obj.2
    { name: "And", age: 45 },
    { name: "The", age: -12 },
    { name: "Magentic", age: 13 },
    { name: "Zero", age: 37 }
];

// 내림 차순 정렬 해보기
let descArr = items.sort(function (obj1, obj2) {
    return obj2.age - obj1.age;
});
// 화살표 함수로 나타내보기
let descArr1 = items.sort((obj1, obj2) => obj2.age - obj1.age);

console.log(descArr);

// 오름 차순 정렬 해보기
let ascArr = items.sort(function (obj1, obj2) {
    return obj1.age - obj2.age;
});
// 화살표 함수로 나타내보기
let ascArr1 = items.sort((obj1, obj2) => obj1.age - obj2.age);

console.log(ascArr);

 

* 조건부 sort *

// 조건부 sort

// - 각 객체가 age와 name속성을 가짐
// - 이 배열을 age 속성에 따라 오름차순으로 정렬하되, age가 같은 경우에는 name 속성으로 사전순으로 정렬

let people = [
    { name: 'John', age: 25 },
    { name: 'Jane', age: 20 },
    { name: 'Mary', age: 25 },
    { name: 'Mark', age: 30 },
];

// 1. age 속성에 따라 오름차순(asc: 어센딩)으로 정렬한다.

// let sortedArr = people.sort(function (a, b) {

//     return a.age - b.age;
// });

// 2. age 속성이 같을 경우에는 name 속성으로 정렬한다.
if (a.age === b.age) {
    return a.name - b.name;
}

// 3. 합친다.
// 내가 직접 스스로 만들어 본 코드임

let sortedArr = people.sort(function (a, b) {

    if (a.age === b.age) {
        return a.name - b.name;
    }
   
    return a.age - b.age;
});

console.log(sortedArr);
// 결과
[
    { name: 'Jane', age: 20 },
    { name: 'John', age: 25 },
    { name: 'Mary', age: 25 },
    { name: 'Mark', age: 30 }
  ]

신기하게도 내가 짠 코드가 멀쩡하게 동작을 한다... 오오... 신기해...

- 튜터님의 정답 코드 -

let sortedArr = people.sort(function (a, b) {

    if (a.age === b.age) {
        return a.name.localeCompare(b.name);
    }
    return a.age - b.age;
});
console.log(sortedArr);

// 결과
[
    { name: 'Jane', age: 20 },
    { name: 'John', age: 25 },
    { name: 'Mary', age: 25 },
    { name: 'Mark', age: 30 }
  ]

튜터님과 내 코드의 차이점은 loaleCompare 메서드의 사용 유무이다.

localeCompare 메서드는 문자열과 문자열을 비교하는 메서드이다.
a.name과 b.name의 속성은 문자열을 값으로 가지고 있기 때문에 문자열을 비교해서 정렬하는 localeCompare 메서드를 사용해서 정렬이 가능하다.

localeCompare 예제

 
alert('a'.localeCompare('b')); // -1
alert('b'.localeCompare('a')); // 1
alert('b'.localeCompare('b')); // 0


마치.. sort에서 sort((a, b) => return a - b); 와 비슷한 느낌이 든다...
a.name.localeCompare(b.name);

 

'개발공부' 카테고리의 다른 글

HTTP 모듈로 서버 만들고 실행해보기  (0) 2024.01.18
Node.js 주특기 입문 1일차  (0) 2024.01.17
함수 관련 공부  (0) 2024.01.16
변수 var, let, const  (0) 2024.01.09
내가 공부한 거 정리하는 소박한 공간  (1) 2024.01.08