Сортировка массива объектов по дате - PullRequest
1 голос
/ 16 апреля 2020
[
0: {date: "02-04-2020", count: 1}
1: {date: "16-04-2020", count: 2}
2: {date: "10-04-2020", count: 1}
3: {date: "15-04-2020", count: 4}
4: {date: "04-04-2020", count: 4}
]

Из приведенного выше массива объектов мне нужно отсортировать их по дате и получить вывод следующим образом

    [
    0: {date: "02-04-2020", count: 1}
    1: {date: "04-04-2020", count: 4}
    2: {date: "10-04-2020", count: 1}
    3: {date: "15-04-2020", count: 4}
    4: {date: "16-04-2020", count: 2}
    ]

Я пытался использовать следующий метод

const sorted_array = data
          .slice()
          .sort(
            (a, b) => new Date(a.date).valueOf() - new Date(b.date).valueOf()
          );

Я использовал .slice перед сортировкой, так как получаю ошибку Cannot assign to read only property '0' of object '[object Array], поэтому я сослался на Ошибка при сортировке массива объектов. Невозможно назначить только для чтения свойство '2' объекта '[object Array]' и добавлен фрагмент.

Но сортировка выполнена неправильно, мне нужна помощь, чтобы это исправить. Спасибо.

Ответы [ 3 ]

2 голосов
/ 16 апреля 2020

Обратитесь к ответу @ Джейкоба для объяснения вашей ошибки. Вот альтернативное решение с использованием регулярных выражений, чтобы изменить дату на правильный формат:

const pattern = /(\d{2})-(\d{2})-(\d{4})/;
const repl = "$3-$2-$1";
const sorted_array = data
      .slice()
      .sort(
          (a, b) => new Date(a.date.replace(pattern, repl)) - 
                    new Date(b.date.replace(pattern, repl))
      );

Также обратите внимание, что вам не нужно сравнивать valueOf() с Date s, арифметическое c было перегружен для Date уже для возможности собственного сравнения объектов.

Редактировать: изменен repl на формат ISOYY01-MM-DD, совместимый с ISO 8601, согласно спецификации .

2 голосов
/ 16 апреля 2020

Возможно, вы столкнулись с проблемой, когда new Date(...) не обрабатывает строки этого формата, поскольку это не стандартный формат. new Date("02-04-2020") интерпретирует его как 4 февраля 2020 года, а new Date("16-04-2020") выдает ошибку. Кажется, здесь используются американские форматы дат, где мы используем их задом наперед.

Если бы ваши даты были в формате yyyy-mm-dd, то new Date(...) работало бы правильно, поэтому, если вы сможете изменить это, это будет самый плавный маршрут. Если вы не можете изменить формат, попробуйте изменить сортировку следующим образом:

const sorted_array = data
  .map(addSortableColumn)
  .sort(bySortColumn)
  .map(removeSortableColumn);

function addSortableColumn(item) {
  const [day, month, year] = item.date.split('-');
  return { ...item, _sortBy: year + month + day };
}

function bySortColumn(a, b) {
  return a._sortBy.localeCompare(b._sortBy);
}

function removeSortableColumn(item) {
  const { _sortBy, ...otherProps } = item;
  return otherProps;
}

(если вам не нужно удалять столбец сортировки, вы можете пропустить этот последний шаг)

Обновление

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

const sortKeys = new Map();

const sorted_array = data.slice().sort(byDDMMYYYY);

function byDDMMYYYY(a, b) {
  return getSortKey(a).localeCompare(getSortKey(b));
}

function getSortKey(item) {
  let key = sortKeys.get(item);
  if (!key) {
    const [day, month, year] = item.date.split('-');
    key = year + month + day;
    sortKeys.set(item, key);
  }
  return key;
}
1 голос
/ 16 апреля 2020

Ваш формат даты неверный. ДД-ММ-ГГГГ не является допустимым форматом даты.

new Date("15-04-2020")

вернет Неверная дата

Вам необходимо преобразовать дату в формат даты ИСО ГГГГ-ММ -DD ​​ согласно спецификации .

const data = [ 
  {_id: "02-04-2020", count: 1},
  {_id: "16-04-2020", count: 2},
  {_id: "10-04-2020", count: 1},
  {_id: "15-04-2020", count: 4},
  {_id: "04-04-2020", count: 4},
];

console.log("Original Data: ", data);

// Something like that.
const dataSorted = data.slice().sort((a, b) => {
  const [dayA, monthA, yearA] = a._id.split("-");
  const [dayB, monthB, yearB] = b._id.split("-");
  return new Date(`${yearA}-${monthA}-${dayA}`) 
    - new Date(`${yearB}-${monthB}-${dayB}`)
});

console.log("Data sorted by date: ", dataSorted);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...