Сортировка массива по строковому значению даты не возвращает правильный порядок результатов (по убыванию)

Я пытаюсь отсортировать массив по строковой дате, и у меня возникают некоторые проблемы с ним.

Мой массив называется: myArray и содержит следующую информацию:

0: {…}
​​
deployed_date: "29/01/2019 14:08:44"
​​last_restored_date: "11/01/2019 11:22:22"

1: {…}
​​
deployed_date: "29/01/2019 14:08:19"
​​
2: {…}
​​
​​deployed_date: "29/01/2019 11:34:23"
​​
3: {…}
​​
deployed_date: "11/02/2019 11:24:33"
​​
4: {…}
​​
deployed_date: "11/02/2019 11:24:24"
​​last_restored_date: "11/01/2019 11:25:42"

Я использовал как Lodash, так и нативную сортировку JavaScript, но, к сожалению, я не могу сортировать только по этой дате deployed_date в порядке убывания.

К вашему сведению, я также использую momentjs:

myArray[key].deployed_date = moment(value.deployed_date,'YYYYMMDDHHmmss').format('DD/MM/YYYY HH:mm:ss');

Я использовал:

_.orderBy(myArray, ['deployed_date'],['desc']) // Лодаш

а также

myArray.sort()

Порядок выглядит так, как в моем массиве выше.

Я не уверен, связано ли это с тем фактом, что индексы массива 1,2 и 3 не имеют значения last_restored_date, но по какой-то причине массив неправильно отсортирован по развернутому_дате desc.

Ожидаемый результат:

11/02/2019 11:24:33
11/02/2019 11:24:24
29/01/2019 14:08:44
29/01/2019 14:08:19
29/01/2019 11:34:23

Как я могу добиться ожидаемого порядка результатов, показанного здесь?

какова структура myArray? это массив объектов?

Mister Jojo 11.02.2019 05:57

@MrJ да, это так.

tonyf 11.02.2019 06:01

после сортировки вам нужны только даты на выходе или целые объекты?

molamk 11.02.2019 06:33

весь объект, но в порядке убывания deployed_date, который представляет собой строку

tonyf 11.02.2019 06:34

Пожалуйста, постарайтесь воздержаться от txtspk здесь, Тони - мы ищем здесь читабельный, технический текст, насколько это возможно. Это не фейсбук.

halfer 13.02.2019 21:47

@halfer Нет проблем. К вашему сведению, я не пользуюсь Facebook.

tonyf 14.02.2019 00:44
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
6
355
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Вы можете использовать карту в результирующем массиве, как это, чтобы получить ожидаемый результат

let new_arr = foo.map( (obj) => {  
   return obj.deployed_date;
 ); 

Надеюсь, это имеет смысл

нужно, чтобы это было в порядке убывания

tonyf 11.02.2019 06:04

если сортировка дает неправильный ввод, попробуйте изменить дату на метку времени перед использованием сортировки, а затем преобразовать ее повторно

Yatin Darmwal 11.02.2019 06:11

Не могли бы вы привести краткий пример для случая - спасибо.

tonyf 11.02.2019 06:23

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

Yatin Darmwal 11.02.2019 06:56
Ответ принят как подходящий

Пожалуйста, используйте библиотеку моментов, чтобы сначала отформатировать дату в формате «ДД/ММ/ГГГГ ЧЧ: мм: сс», а приведенный ниже код будет сортировать и возвращать результат, который вы ищете. x.sort((a,b)=>{ return moment(a,'DD/MM/YYY HH:mm:ss').isAfter(moment(b,'DD/MM/YYY HH:mm:ss')) ? -1 : 1 })

Привет. На самом деле использую момент - обновил свой пост выше.

tonyf 11.02.2019 06:00

затем moment(a,'DD/MM/YYY HH:mm:ss').isAfter(moment(b,'DD/MM/YYY HH:mm:ss')) сравнивает даты и соответствующим образом сортирует их.

Vikash_Singh 11.02.2019 06:05

Я попробовал ваше решение, используя moment(a.deployed_date, 'DD/MM/YYY HH:mm:ss').isAfter(moment(b.deployed_date,'DD/MM/YYY HH:mm:ss')), который, похоже, возвращает набор результатов в порядке убывания. Это b/c isAfter?

tonyf 11.02.2019 11:27

если вы хотите получить результат в порядке возрастания, верните 1, если условие удовлетворяет, иначе верните -1, например: return moment(a,'DD/MM/YYY HH:mm:ss').isAfter(moment(b,'DD/MM/YYY HH:mm:ss')) ? 1 : -1

Vikash_Singh 12.02.2019 06:21

Одним из решений является преобразование ваших дат в стандартный формат при сравнении deployed_date двух объектов с использованием Строка::localeCompare():

const myArray = [
  {deployed_date: "29/01/2019 14:08:44", last_restored_date: "11/01/2019 11:22:22"},
  {deployed_date: "29/01/2019 14:08:19"},
  {deployed_date: "29/01/2019 11:34:23"},
  {deployed_date: "11/02/2019 11:24:33"},
  {deployed_date: "11/02/2019 11:24:24", last_restored_date: "11/01/2019 11:25:42"}
];

myArray.sort((a, b) =>
{
    let [aDate, aHour] = a.deployed_date.split(" ");
    let [bDate, bHour] = b.deployed_date.split(" ");
    let [aDay, aMonth, aYear] = aDate.split("/");
    let [bDay, bMonth, bYear] = bDate.split("/");
    let newADate = `${aYear}/${aMonth}/${aDay} ${aHour}`;
    let newBDate = `${bYear}/${bMonth}/${bDay} ${bHour}`;
    
    return newBDate.localeCompare(newADate);
});

console.info(myArray);

как бы я использовал ваше решение, если бы я использовал момент, как описано выше?

tonyf 11.02.2019 06:36

@tonyf Когда я читал вопрос, этого не было. Однако то, что я вижу, deployed_date - это строка, потому что moment.format() возвращает строку, поэтому предыдущее должно работать. У вас есть какая-то конкретная ошибка?

Shidersz 11.02.2019 06:47

const toDate = str => {
  const [d, t] = str.split(' ')
  return new Date(`${d.split('/').reverse().join('-')}T${t}Z`).getTime();
};

const compareByDate = (x, y) => toDate(y.deployed_date) - toDate(x.deployed_date);

const arr = [
  {deployed_date: "29/01/2019 14:08:44"},
  {deployed_date: "29/01/2019 14:08:19"},
  {deployed_date: "29/01/2019 11:34:23"},
  {deployed_date: "11/02/2019 11:24:33"},
  {deployed_date: "11/02/2019 11:24:24"}
];

arr.sort(compareByDate);
console.info(arr);

Объяснение

  1. Преобразование каждой даты в строку даты ISO (стандартный формат)
  2. Извлеките число из этой строки (используя Date.getTime()) для облегчения сравнения. Используйте конструктор Дата, чтобы изменить строку на дату. Затем конвертируйте эту дату в миллисекунды
  3. Поскольку вам нужен убывающий порядок (обратный), убедитесь, что в вашем функция сравнения вы обращаете операнды. (x, y) => y - x;
  4. Если у вас есть числа в качестве дат, вы можете использовать Массив.сортировка на основе ключа deployed_date

Примечание

Мы хотим использовать формат ISO YYYY-MM-DDTHH:MM:SSZ. А так как у нас есть 29/01/2019 14:08:44 нам нужно сделать некоторую обработку.

  1. Разделите строку с ' ', чтобы разделить время и Дата
  2. Поскольку разделение возвращает массив из 2 элементов, вы можете использовать операцию деструктуризация массива.
  3. Разделите дату на '/' и переверните массив, так как нам нужен YYYY-MM_DD. Затем join с использованием символа '-'
  4. Создайте дату с помощью new Date(...), затем конвертируйте ее в миллисекунды с помощью Date.getMilliseconds()

Как я это вижу, вы хорошо используете orderBy lodash, и он должен был упорядочить ваши данные, как и ожидалось. Что вызывает у вас проблемы, так это то, что вы сортируете строки, а не даты, и ваши строки имеют формат ДД/ММ/ГГГГ, который не идеален, если вы хотите их сортировать: 01/01/2019 «до» 31/12/2018 (хотя и бессмысленно).

Что ты можешь сделать: 1/ вы можете иметь данные даты или момента вместо строк 2/или отформатируйте даты как ГГГГ-ММ-ДД... и т.д. 3/ или передать функцию сортировке ˋ_.orderBy(myArray, [d => moment(d.deployed_data, ...)], ['desc'])`

Другие вопросы по теме