자바스크립트에서 배열을 정렬할 때는 sort() 함수나 toSorted() 함수를 사용한다.
배열을 상대로 sort() 함수를 호출하면 해당 배열 내의 값들이 오름차순으로 정렬한다.
[3, 1, 2].sort();
// [1, 2, 3]
sort() 함수는 원래 배열 내에 값들을 재배치하며 정렬한 원래 배열을 다시 반환한다.
즉 sort() 함수가 반환한 배열은 sort() 함수를 호출한 원래 배열과 동일하다.
const nums = [3, 1, 2];
const sortedNums = nums.sort();
console.log({ nums, sortedNums });
// {
// nums: [1, 2, 3],
// sortedNums: [1, 2, 3]
// }
nums === sortedNums; // true
참고
sort() 함수의 기본 정렬 순서는 문자열의 유니코드 코드 포인트를 따른다.
- 따라서 숫자 배열을 정렬 할때, 이런 식으로 뜬다.
//숫자 배열 [100, 3, 1, 20].sort(); // [1, 100, 20, 3] //음수 포함한 배열 [-3, 2, 0, 1, 3, -2, -1].sort(); // [-1, -2, -3, 0, 1, 2, 3]
sort() 함수로 정렬을 할 때 원본 배열을 건드리지 않아야하는 경우에는 반드시 배열을 먼저 복제한 후에 배열 사본을 상대로 정렬을 해야한다.
const nums = [3, 1, 2];
const sortedNums = [...nums].sort(); // 배열 사본 만들기
console.log({ nums, sortedNums });
// {
// nums: [3, 1, 2],
// sortedNums: [1, 2, 3]
// }
toSorted() 함수를 사용하면 원본 배열을 건드리지 않고 정렬된 배열 사본을 바로 얻을 수 있다.
toSorted() 함수가 반환한 배열은 원래 배열과 다르다.
const nums = [3, 1, 2];
const sortedNums = nums.toSorted();
console.log({ nums, sortedNums });
// {
// nums: [3, 1, 2],
// sortedNums: [1, 2, 3]
// }
nums === sortedNums; // false
기본 정렬 순서가 문자열의 유니코드 코드 포인트이기 때문에 숫자를 어떻게 정렬해야 할까라는 고민이 있을 수 있는데, 다행히 배열을 제대로 정렬할 수 있는 방법이 있다.
바로 sort 함수의 매개변수로 compareFunction을 보내는 것이다.
arr.sort([compareFunction]);compareFunction: 정렬 순서를 정의하는 함수sort() 함수는 인자로 정렬 기준을 나타내는 콜백 함수를 받는다.
이 대소비교를 위한 함수에는 2개의 인자가 넘어오며 다음과 같은 규칙을 따라야 한다.
숫자 오름 차순: 첫 번째 인자 - 두번째 인자 (a - b)
[-3, 2, 0, 1, 3, -2, -1].sort((a, b) => a - b);
// [-3, -2, -1, 0, 1, 2, 3]
숫자 내림 차순: 두번째 인자 - 첫 번째 인자 (b - a)
[-3, 2, 0, 1, 3, -2, -1].sort((a, b) => b - a);
// [3, 2, 1, 0, -1, -2, -3]
const countries = [
{ no: 1, code: "KR", name: "Korea" },
{ no: 2, code: "CA", name: "Canada" },
{ no: 3, code: "US", name: "United States" },
{ no: 4, code: "GB", name: "United Kingdom" },
{ no: 5, code: "CN", name: "China" },
];
정렬 기준이 없으므로 기존 배열 그대로 뜬다.
좀 더 엄밀히 얘기하면 자바스크립트에서 객체를 문자열로 변환하면 [object Object]가 되어 배열 내의 모든 객체의 크기가 동일하다고 판단한다.
countries.sort();
console.log(countries);
// [
// { no: 1, code: 'KR', name: 'Korea' },
// { no: 2, code: 'CA', name: 'Canada' },
// { no: 3, code: 'US', name: 'United States' },
// { no: 4, code: 'GB', name: 'United Kingdom' },
// { no: 5, code: 'CN', name: 'China' }
// ]
국가 코드 기준으로 정렬을 해보자.
숫자가 아니기 때문에 뺄셈을 하는 대신에 문자열의 localeCompare() 메서드를 사용하여 비교한다.
console.log("a".localeCompare("b")); // -1
console.log("b".localeCompare("a")); // 1
console.log("b".localeCompare("b")); // 0
countries.sort((a, b) => a.code.localeCompare(b.code));
console.log(countries);
// [
// { no: 2, code: 'CA', name: 'Canada' },
// { no: 5, code: 'CN', name: 'China' },
// { no: 4, code: 'GB', name: 'United Kingdom' },
// { no: 1, code: 'KR', name: 'Korea' },
// { no: 3, code: 'US', name: 'United States' }
// ]
countries.sort((a, b) => b.code.localeCompare(a.code));
console.log(countries);
// [
// { no: 3, code: 'US', name: 'United States' },
// { no: 1, code: 'KR', name: 'Korea' },
// { no: 4, code: 'GB', name: 'United Kingdom' },
// { no: 5, code: 'CN', name: 'China' },
// { no: 2, code: 'CA', name: 'Canada' }
// ]
다양한 속성을 가진 사용자들을 담은 배열을
const users = [
{
mail: "gregorythomas@gmail.com",
name: "Brett Holland",
gender: "M",
age: 73,
},
{
mail: "hintc12@hotmail.com",
name: "Madison Martinez",
gender: "F",
age: 29,
},
{
mail: "wwagner33@gmail.com",
name: "Michael Jenkins",
gender: "M",
age: 51,
},
{
mail: "ujacksonxejyen@gmail.com",
name: "Amber Rhodes",
gender: "F",
age: 42,
},
{
mail: "daniel7900@gmail.com",
name: "Karen Rodriguez",
gender: "F",
age: 32,
},
];
성별을 기준으로 1차 내림차순 정렬하고,
나이 기준으로 2차 오름차순 정렬을 하려면?
//성별 내림 차순 b-a
users.sort((a, b) => b.gender.localeCompare(a.gender));
//나이 오름 차순 a-b
users.sort((a, b) => a.age - b.age);
//✅ 합치기
//성별 내림 차순 b-a : M > F 순으로
users.sort((a, b) => {
if (a.gender === b.gender) { // 성별이 같을 경우에는
return a.age - b.age; //나이 오름 차순(작은것 부터 큰 순서대로) a-b 로 하기
}
return b.gender.localeCompare(a.gender);
});
console.log(users); // 동일한 배열에서 작업 수행
// [
// {
// mail: 'wwagner33@gmail.com',
// name: 'Michael Jenkins',
// gender: 'M',
// age: 51
// },
// {
// mail: 'gregorythomas@gmail.com',
// name: 'Brett Holland',
// gender: 'M',
// age: 73
// },
// {
// mail: 'hintc12@hotmail.com',
// name: 'Madison Martinez',
// gender: 'F',
// age: 29
// },
// {
// mail: 'daniel7900@gmail.com',
// name: 'Karen Rodriguez',
// gender: 'F',
// age: 32
// },
// {
// mail: 'ujacksonxejyen@gmail.com',
// name: 'Amber Rhodes',
// gender: 'F',
// age: 42
// }
// ]
📚 MDN: Array.prototype.sort()
📚 daleseo: 자바스크립트 배열 정렬: sort()와 toSorted() 함수