Сортировка массива объектов по строковому свойству: разбираем популярный вопрос с Stack Overflow
Представьте: у вас есть список пользователей, товаров или статей. Каждый элемент — это объект с кучей свойств: имя, цена, дата, рейтинг. И вам нужно отсортировать всё это, скажем, по фамилии в алфавитном порядке. Задача, которая кажется простой, но на практике подкидывает сюрпризы. Неудивительно, что вопрос "Sort array of objects by string property value" на Stack Overflow собрал тысячи просмотров и десятки ответов.
В этой статье мы не просто дадим готовый код. Мы разберём 5 способов сортировки, от базового до продвинутого, выявим типичные грабли и покажем, как их обойти. К концу вы сможете сортировать любые данные одной левой.
Что такое сортировка массива объектов в JavaScript?
В JavaScript есть встроенный метод Array.prototype.sort(). Но с объектами он работает неочевидно. Если вызвать sort() без аргументов, он попытается сравнивать элементы как строки. Для чисел это даёт сюрприз: [1, 20, 3].sort() вернёт [1, 20, 3], а не [1, 3, 20]. Для объектов — полный хаос.
Поэтому нам нужна функция сравнения (comparator). Она принимает два элемента и возвращает:
- отрицательное число, если первый элемент меньше второго;
- 0, если равны;
- положительное число, если первый больше.
Вот базовая структура сортировки массива объектов по строковому свойству:
// Исходный массив
const users = [
{ name: 'Иван', age: 25 },
{ name: 'Анна', age: 30 },
{ name: 'Борис', age: 22 }
];
// Сортировка по полю name
users.sort((a, b) => {
if (a.name < b.name) return -1;
if (a.name > b.name) return 1;
return 0;
});
console.log(users);
// [{ name: 'Анна', age: 30 }, { name: 'Борис', age: 22 }, { name: 'Иван', age: 25 }]
Этот код работает, но он громоздкий. Давайте посмотрим, как сделать его элегантнее.
5 способов отсортировать массив объектов по строке
Способ 1: Классическая функция сравнения
Самый прозрачный метод. Подходит для любых строк, включая кириллицу, при условии, что вы используете правильный алфавитный порядок. Сравнение через < и > учитывает коды символов в Unicode, что для русского языка даёт неожиданный результат: «ё» окажется в конце алфавита, а «я» — рядом с «а».
const products = [
{ title: 'Яблоко', price: 50 },
{ title: 'Ёлка', price: 200 },
{ title: 'Ананас', price: 150 }
];
// Проблема: 'Ёлка' встанет после 'Яблоко'
products.sort((a, b) => {
if (a.title < b.title) return -1;
if (a.title > b.title) return 1;
return 0;
});
Когда использовать: для английских строк, где алфавитный порядок совпадает с Unicode.
Способ 2: localeCompare — спаситель кириллицы
Метод String.prototype.localeCompare() учитывает правила сортировки для конкретного языка. Для русского — передаём 'ru'.
users.sort((a, b) => a.name.localeCompare(b.name, 'ru'));
console.log(users);
// [{ name: 'Анна', age: 30 }, { name: 'Борис', age: 22 }, { name: 'Иван', age: 25 }]
Этот код чище, короче и правильно обрабатывает «ё», «й» и другие буквы. Если нужно отсортировать по убыванию — просто поменяйте местами a и b:
users.sort((a, b) => b.name.localeCompare(a.name, 'ru'));
Когда использовать: всегда, когда работаете с кириллицей или многоязычными данными.
Способ 3: Сортировка с учётом регистра
По умолчанию localeCompare чувствителен к регистру: «apple» встанет перед «Banana», потому что строчная буква имеет больший Unicode-код. Если нужно игнорировать регистр, добавьте опцию { sensitivity: 'base' }.
const mixed = [
{ name: 'apple' },
{ name: 'Banana' },
{ name: 'Apple' }
];
// Без опции: Banana, Apple, apple
mixed.sort((a, b) => a.name.localeCompare(b.name));
// С опцией: apple, Apple, Banana (регистр не важен)
mixed.sort((a, b) => a.name.localeCompare(b.name, 'en', { sensitivity: 'base' }));
Способ 4: Сортировка по вложенным свойствам
Часто объекты имеют вложенную структуру. Например, у пользователя есть адрес с городом. Как отсортировать по городу?
const people = [
{ name: 'Иван', address: { city: 'Москва' } },
{ name: 'Анна', address: { city: 'Астрахань' } },
{ name: 'Борис', address: { city: 'Волгоград' } }
];
people.sort((a, b) => a.address.city.localeCompare(b.address.city, 'ru'));
console.log(people);
// Анна (Астрахань), Борис (Волгоград), Иван (Москва)
Если свойство может отсутствовать, добавьте проверку:
people.sort((a, b) => {
const cityA = a.address?.city || '';
const cityB = b.address?.city || '';
return cityA.localeCompare(cityB, 'ru');
});
Способ 5: Динамическая сортировка по любому свойству
А что, если пользователь сам выбирает поле для сортировки? Создадим универсальную функцию:
function sortByProperty(arr, prop, locale = 'ru') {
return arr.sort((a, b) => {
const valA = a[prop] || '';
const valB = b[prop] || '';
return valA.localeCompare(valB, locale);
});
}
// Пример использования
const sortedByName = sortByProperty(users, 'name');
const sortedByTitle = sortByProperty(products, 'title');
Совет: Для обратной сортировки передавайте флаг desc и меняйте порядок a и b.
Частые вопросы (FAQ) по сортировке объектов в JavaScript
Почему sort() без аргументов не работает для чисел?
Потому что sort() преобразует элементы в строки. [1, 20, 3].sort() даёт [1, 20, 3], так как
Блоги
Рекомендаций по книгам
Читайте также
Монорепозиторий с Go: организация кода для начинающих
C# Accessibility: пишем код, который могут использовать все
Как устроиться Swift разработчиком: советы и резюме на практике
Как вытащить сырой SQL из Query Builder в PHP: 3 рабочих метода
Покрытие кода тестами в Java: от JUnit до JaCoCo на практике