Как отсортировать/упорядочить список по дате в dart/flutter?

У меня есть следующий список, который я пытаюсь переупорядочить/сортировать по DateTime.

import 'package:intl/intl.dart'; 
//don't forget to add under dependencies pubspec.yml "intl: ^0.15.8"


List products = [];

//adding into the new list from raw API list
for(final item in rawProducts){

   var parsedDate = DateTime.parse.(item['expiryDate']);
   tmpArray = {
     'id': item['id'],
     'name': item['name'],
     'price': item['price'],
     'expiry': parsedDate
   }
   products.add(tmpArray);
  }
}


List products = [

 {id: 1242, name: milk, price: $5, expiry: 2019-11-25 00:00:00:000},
 {id: 1242, name: egg, price: $2, expiry: 2019-11-22 00:00:00:000},
 {id: 1243, name: bread, price: $3, expiry: 2019-11-22 00:00:00:000},
 {id: 1244, name: butter, price: $7, expiry: 2019-11-24 00:00:00:000},
 {id: 1247, name: butter, price: $7, expiry: 2019-11-23 00:00:00:000},

]

Я хотел бы изменить порядок списка таким образом, чтобы самая дальняя дата истечения срока действия отображалась первой:

 25-11-2019
 24-11-2019
 23-11-2019
 22-11-2019
 22-11-2019

Что я пробовал (обновлял) -> РЕШЕНО, заменив a.expiry на a['expiry']:

  products.sort((a,b) {
    var adate = a['expiry'] //before -> var adate = a.expiry;
     var bdate = b['expiry'] //var bdate = b.expiry;
     return -adate.compareTo(bdate);
  });

в функции сортировки я получаю эту ошибку (РЕШЕНО вышеуказанным исправлением):

Unhandled Exception: NoSuchMethodError: Class 
'_InternalLinkedHashMap<String, dynamic>'has no instance getter 'expiry'.

см. DateFormat.parse метод

pskink 12.07.2019 06:31

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

Manas 12.07.2019 08:26
final format = DateFormat('yyyy-M-d H:m:s:S'); final array = [ '2019-11-24 00:00:00:000', '2019-11-22 00:00:00:000', '2019-11-23 00:00:00:000', '2019-11-25 00:00:00:000', '2019-11-22 00:00:00:000', ]; array.map(format.parse).toList() ..sort((a, b) => -a.compareTo(b)) ..forEach(print);
pskink 12.07.2019 08:40

спасибо @pskink, кажется, ошибка на самом деле исходит от метода сортировки, пытающегося получить expiry, выдает эту ошибку: Unhandled Exception: NoSuchMethodError: Class '_InternalLinkedHashMap<String, dynamic>' has no instance getter 'expiry'

Manas 12.07.2019 08:57

спасибо, @pskink, да, я получаю эту ошибку «нет экземпляра геттера с истечением срока действия», см. Последний сегмент вопроса выше.

Manas 12.07.2019 09:09

нет, в моем коде нет expiry, сначала запустите мой код как есть (без каких-либо изменений), посмотрите, как он работает, и, наконец, соответствующим образом измените свой код - в основном ключ находится в конструкторе DateFormat() и как обрабатывается метод sort

pskink 12.07.2019 09:15

@pskink, спасибо!! я заставил его работать, извините, да, я не запускал ваш код отдельно, моя ошибка заключалась в том, что я просто модифицировал свои собственные коды. Так что на самом деле это было в a.expiry, я переключил его на a['expiry'], теперь он правильно переупорядочивает, я попытался переключить adate.compareTo(bdate) и -bdate.compareTo(adate), чтобы подтвердить, и заказ работает потрясающе! Спасибо большое. Вы можете опубликовать это как ответ, чтобы я мог отметить это, пожалуйста?

Manas 12.07.2019 09:19

конечно, добро пожаловать, не стесняйтесь публиковать ответ на свой вопрос

pskink 12.07.2019 09:26

Я опубликовал свой ответ, спасибо @pskink!! удачного кодирования :)

Manas 12.07.2019 09:35
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
65
9
63 872
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

В приведенном выше примере expiry — это String, а не объект DateTime. Здесь у вас есть несколько вариантов, в зависимости от того, чего вы хотите достичь.

Самым простым решением было бы использовать встроенный в String метод compareTo, который позволяет сортировать строки. Эти временные метки уже находятся в сортируемом формате, так что это сработает:

products.sort((a,b) {
    return a.compareTo(b);
 });

Или более кратко:

products.sort((a,b) => a.compareTo(b));

Это довольно просто. Как и pskink, упомянутый в комментарии, основываясь на этом, вы можете преобразовать строки в фактические объекты DateTime.

DateTime expiryAsDateTime = DateTime.parse(expiry);

DateTime также имеет встроенный метод compareTo, поэтому приведенный выше фрагмент кода будет работать как с DateTimes, так и со строками.

Если вы хотите изменить порядок, просто поменяйте местами a и b.

спасибо @MichaelM за ваш ответ, я уже проанализировал дату, прежде чем назначать ее в список продуктов. Кстати, какой порядок это на самом деле вернет? что, если я хочу противоположный порядок, как я могу изменить эту функцию, которую вы упомянули выше products.sort((a,b) => a.compareTo(b));

Manas 12.07.2019 08:35

compareTo сортирует в порядке возрастания. Если вы хотите поменять порядок, вы можете просто сделать это: products.sort((a,b) => b.compareTo(a)); Я связал документацию в своем ответе.

MichaelM 12.07.2019 09:07

Приятно! спасибо @MichaelM, теперь ошибка в основном связана с функцией сортировки после проверки журнала, я думаю, что функция сортировки не может получить доступ к expiry в списке. пожалуйста, посмотрите последний сегмент моего обновленного вопроса об ошибке

Manas 12.07.2019 09:11

Спасибо! Я исправил ошибку, используя ваш первый предложенный метод!

Manas 12.07.2019 09:37

конвертировать в DateTime

import 'package:intl/intl.dart';

void main() {
  List products = [
    "2019-11-25 00:00:00.000",
    "2019-11-22 00:00:00.000",
    "2019-11-22 00:00:00.000",
    "2019-11-24 00:00:00.000",
    "2019-11-23 00:00:00.000"
  ];
  List<DateTime> newProducts = [];
  DateFormat format = DateFormat("yyyy-MM-dd");

  for (int i = 0; i < 5; i++) {
    newProducts.add(format.parse(products[i]));
  }
  newProducts.sort((a,b) => a.compareTo(b));

  for (int i = 0; i < 5; i++) {
    print(newProducts[i]);
  }
}

без преобразования в DateTime

import 'package:intl/intl.dart';

void main() {
  List products = [
    "2019-11-25 00:00:00.000",
    "2019-11-22 00:00:00.000",
    "2019-11-22 00:00:00.000",
    "2019-11-24 00:00:00.000",
    "2019-11-23 00:00:00.000"
  ];

  products.sort((a,b) => a.compareTo(b));

  for (int i = 0; i < 5; i++) {
    print(products[i]);
  }
}

Я исправил это, изменив changing a.expiry into a['expiry'] и b.expiry into b['expiry']

products.sort((a,b) {
 var adate = a['expiry'] //before -> var adate = a.expiry;
 var bdate = b['expiry'] //before -> var bdate = b.expiry;
 return adate.compareTo(bdate); //to get the order other way just switch `adate & bdate`
});

Если вы хотите отсортировать объекты по имени свойства без использования DateTime, предполагая, что дата и время являются строкой, сделайте следующее:

products.sort((a, b)=> a['expiry'].compareTo(b['expiry']));

Если у вас есть что-то вроде:

{
"id": 100,
"timestamp": "2021-02-02T15:15:11Z",
"name": "Entry1"
}

Затем сделайте следующее:

List<Values> _myList = [];
_myList.sort((a,b)=> a["timestamp"].compareTo(b["timestamp"])); 

Или как в моем коде:

task.sort((a,b) => a.createdAt.compareTo(b.createdAt));

Источник

Если мы станем более конкретными, то попробуйте, как этот.

это сработало отлично для меня


transactionList.sort((a, b) {
  int aDate = DateTime.parse(a.dateTime ?? '').microsecondsSinceEpoch;
  int bDate = DateTime.parse(b.dateTime ?? '').microsecondsSinceEpoch;
  return aDate.compareTo(bDate);
});

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