Другое

Полное руководство: сортировка массива объектов по дате в JavaScript

Узнайте, как сортировать массивы объектов по свойству даты в JavaScript. Полное руководство с примерами для сортировки в порядке убывания, обработки разных форматов и оптимизации производительности.

Как отсортировать массив объектов по свойству даты в JavaScript?

У меня есть массив объектов со свойствами даты:

javascript
var array = [
  {id: 1, date: "Mar 12 2012 10:00:00 AM"}, 
  {id: 2, date: "Mar 8 2012 08:00:00 AM"}
];

Как можно отсортировать этот массив по элементу даты в порядке от даты, ближайшей к текущей дате и времени, и далее? Массив может содержать много объектов, но для примера я упростил его до двух.

Стоит ли мне использовать функцию sort() с пользовательским компаратором для достижения этого?

Сортировка массива объектов по свойству даты в JavaScript

Чтобы отсортировать массив объектов по свойству даты в JavaScript от ближайшей к текущей дате/времени вниз (в порядке убывания), следует использовать метод sort() с функцией-компаратором, которая преобразует строки дат в объекты Date и сравнивает их численно. Наиболее эффективный подход — вычитание значений дат для получения численного сравнения.

Содержание

Базовый подход к сортировке

Фундаментальный подход к сортировке массива объектов по свойству даты involves использование встроенного метода Array.prototype.sort() JavaScript с функцией-компаратором. Эта функция преобразует строки дат в объекты Date и сравнивает их численно.

Для вашего примера массива:

javascript
var array = [
  {id: 1, date: "Mar 12 2012 10:00:00 AM"}, 
  {id: 2, date: "Mar 8 2012 08:00:00 AM"}
];

Вы можете отсортировать его в порядке убывания (сначала самые новые) с помощью этого компаратора:

javascript
array.sort((a, b) => new Date(b.date) - new Date(a.date));

Это работает потому, что когда вы вычитаете одну дату из другой в JavaScript, они автоматически преобразуются в временные метки (числа, представляющие миллисекунды с 1 января 1970 года), что позволяет провести численное сравнение. Метод sort использует возвращаемое значение для определения порядка:

  • Положительное значение: a идет после b (порядок убывания)
  • Отрицательное значение: a идет перед b (порядок возрастания)
  • Ноль: элементы остаются без изменений

Обработка различных форматов дат

Ваш массив содержит строки дат в формате “Mar 12 2012 10:00:00 AM”, но JavaScript может обрабатывать различные форматы дат. Ключевое — обеспечить согласованность в том, как вы парсите даты.

Для того же формата, который вы предоставили:

javascript
array.sort((a, b) => new Date(b.date) - new Date(a.date));

Для ISO-строк дат (например, "2022-01-01T12:30:00.000Z"):

javascript
array.sort((a, b) => new Date(b.date) - new Date(a.date));

Для объектов Date, уже хранящихся в массиве:

javascript
array.sort((a, b) => b.date - a.date);

Для значений временных меток:

javascript
array.sort((a, b) => b.date - a.date);

Сеть разработчиков Mozilla объясняет, что конструктор new Date() может парсить различные форматы строк дат, что делает его универсальным для различных вариантов использования.

Порядок убывания и возрастания

Чтобы получить сортировку от даты, ближайшей к текущей дате/времени, вниз (сначала самые новые), вам нужен порядок убывания. Вот как реализовать оба варианта:

Порядок убывания (сначала самые новые):

javascript
array.sort((a, b) => new Date(b.date) - new Date(a.date));

Порядок возрастания (сначала самые старые):

javascript
array.sort((a, b) => new Date(a.date) - new Date(b.date));

Как объясняется на Mastering JS, вы можете просто вычесть два свойства даты в обратном вызове сортировки, чтобы получить желаемый порядок. Для порядка убывания вычитайте первую дату из второй; для порядка возрастания — вторую из первой.

Рекомендации по производительности

При сортировке больших массивов объектов со свойствами дат учитывайте эти оптимизации производительности:

  1. Избегайте повторного создания объектов Date: Если вы сортируете один и тот же массив несколько раз, рассмотрите возможность преобразования дат в временные метки один раз:

    javascript
    // Предварительно вычисляем временные метки для лучшей производительности
    array.forEach(obj => obj.timestamp = new Date(obj.date).getTime());
    array.sort((a, b) => b.timestamp - a.timestamp);
    
  2. Используйте численные сравнения: Прямое численное сравнение быстрее, чем сравнение объектов Date:

    javascript
    array.sort((a, b) => +b.date - +a.date); // Использование унарного плюса
    
  3. Учитывайте стабильную сортировку: Метод sort() в JavaScript не гарантирует стабильности, но современные движки предоставляют стабильную сортировку. Для сложных потребностей в сортировке, возможно, потребуется реализовать более надежное решение.

Согласно GeeksforGeeks, встроенный метод сортировки с объектами Date обеспечивает хорошую производительность для большинства случаев использования, но для очень больших наборов данных предварительное вычисление временных меток может быть полезным.

Альтернативные подходы

Использование метода getTime() объекта Date

Для более явного контроля над сравнением дат:

javascript
array.sort((a, b) => b.date.getTime() - a.date.getTime());

Этот подход особенно полезен, когда ваши свойства дат уже являются объектами Date, а не строками.

Использование внешних библиотек

Для более сложных манипуляций с датами рассмотрите возможность использования библиотек, таких как date-fns или moment.js:

javascript
import { compareDesc } from 'date-fns';

array.sort((a, b) => compareDesc(new Date(a.date), new Date(b.date)));

Библиотека date-fns предоставляет специализированные функции для сравнения дат и может обрабатывать более сложные сценарии, как часовые пояса и локализацию.

Преобразование Шварца (decorate-sort-undecorate)

Для очень больших массивов или когда производительность критична, вы можете использовать преобразование Шварца:

javascript
// Декорируем временными метками
const decoratedArray = array.map(obj => ({
  ...obj,
  timestamp: new Date(obj.date).getTime()
}));

// Сортируем по временным меткам
decoratedArray.sort((a, b) => b.timestamp - a.timestamp);

// Убираем декорацию (удаляем временные свойства)
const sortedArray = decoratedArray.map(({timestamp, ...rest}) => rest);

Как отмечено на Stack Overflow, этот подход уменьшает количество преобразований объектов Date во время сортировки.

Полные практические примеры

Пример 1: Базовая реализация

javascript
var array = [
  {id: 1, date: "Mar 12 2012 10:00:00 AM"}, 
  {id: 2, date: "Mar 8 2012 08:00:00 AM"},
  {id: 3, date: "Mar 15 2012 02:00:00 PM"}
];

// Сортируем в порядке убывания (сначала самые новые)
array.sort((a, b) => new Date(b.date) - new Date(a.date));

console.log(array);
/*
Вывод:
[
  {id: 3, date: "Mar 15 2012 02:00:00 PM"},
  {id: 1, date: "Mar 12 2012 10:00:00 AM"},
  {id: 2, date: "Mar 8 2012 08:00:00 AM"}
]
*/

Пример 2: Сортировка по расстоянию от текущей даты

Если вы хотите отсортировать по тому, насколько близка каждая дата к текущей (сначала ближайшие):

javascript
var array = [
  {id: 1, date: "Mar 12 2012 10:00:00 AM"}, 
  {id: 2, date: "Mar 8 2012 08:00:00 AM"},
  {id: 3, date: new Date().toISOString()} // Текущая дата
];

const now = new Date();

// Сортируем по абсолютному расстоянию от текущей даты
array.sort((a, b) => {
  const distanceA = Math.abs(now - new Date(a.date));
  const distanceB = Math.abs(now - new Date(b.date));
  return distanceA - distanceB;
});

console.log(array);

Пример 3: Повторно используемая функция сортировки

Для лучшей организации кода создайте повторно используемую функцию сортировки:

javascript
function sortByDateDescending(array, dateProperty) {
  return array.slice().sort((a, b) => {
    const dateA = new Date(a[dateProperty]);
    const dateB = new Date(b[dateProperty]);
    return dateB - dateA;
  });
}

// Использование
var array = [
  {id: 1, date: "Mar 12 2012 10:00:00 AM"}, 
  {id: 2, date: "Mar 8 2012 08:00:00 AM"}
];

const sorted = sortByDateDescending(array, 'date');
console.log(sorted);

Sling Academy предоставляет отличные примеры реализации этих шаблонов сортировки в реальных приложениях.


Источники

  1. Stack Overflow - How to sort an object array by date property
  2. GeeksforGeeks - Sort an Object Array by Date in JavaScript
  3. Mastering JS - How to Sort an Array by Date in JavaScript
  4. Sling Academy - JavaScript: Sorting an Array of Objects by Date Property
  5. Stack Abuse - How to Sort an Array by Date in JavaScript
  6. By By Dev - How to sort an array by date value in JavaScript
  7. Coding Beauty - How to Sort an Object Array By Date in JavaScript
  8. Medium - How to Sort an Object Array by Date in JavaScript

Заключение

Чтобы обобщить ключевые моменты сортировки массива объектов по свойству даты в JavaScript:

  1. Используйте метод sort() с функцией-компаратором — Это наиболее прямой и эффективный подход для вашего случая использования.

  2. Преобразуйте строки дат в объекты Date — Используйте new Date() для парсинга строковых дат перед сравнением.

  3. Для порядка убывания (сначала самые новые) вычитайте первую дату из второй: new Date(b.date) - new Date(a.date).

  4. Учитывайте оптимизации производительности для больших массивов, такие как предварительное вычисление временных меток или использование преобразования Шварца.

  5. Обрабатывайте различные форматы дат, обеспечивая согласованное парсинг с помощью конструктора new Date().

Подход, который вы определили с использованием sort() с функцией-компаратором, действительно является правильным и наиболее эффективным методом сортировки массивов объектов по свойствам дат в JavaScript. Этот подход обеспечивает как гибкость, так и хорошую производительность для большинства реальных приложений.

Авторы
Проверено модерацией
Модерация