Как получить последнюю запись в день из массива в Javascript? - PullRequest
0 голосов
/ 06 апреля 2020

Ну, этот вопрос может звучать немного странно, но я объясню.
У меня есть массив в Javascript, который приходит из API, как это:

[
    {IdLocal: 12, Date: 04-06-2020T15:25},
    {IdLocal: 12, Date: 04-06-2020T10:37},
    {IdLocal: 12, Date: 04-05-2020T12:30},
    {IdLocal: 12, Date: 04-05-2020T13:40}
    {IdLocal: 13, Date: 04-06-2020T15:25},
    {IdLocal: 13, Date: 04-06-2020T10:37},
    {IdLocal: 13, Date: 04-05-2020T12:30},
    {IdLocal: 13, Date: 04-05-2020T13:40}
]

И что я хочу способ найти последнюю запись для каждого локального элемента в день
например: для данного массива я хочу получить ответ типа:

[
   {IdLocal: 12, Date: 04-06-2020T15:25}, // the latest in local 12, day 06
   {IdLocal: 12, Date: 04-05-2020T13:40}, // the latest in local 12, day 05
   {IdLocal: 13, Date: 04-06-2020T15:25}, // the latest in local 13, day 06
   {IdLocal: 13, Date: 04-05-2020T13:40}  // the latest in local 13, day 05
]

Как видите, я хочу это просто возвращать последнюю запись от каждого Local за каждый день.

Я думаю, что итерация снова и снова моего массива может стать очень дорогой, если возвращаемый массив станет огромным.
Я знаю, что современные Javascript действительно полезные методы массива, такие как .map и .filter, но я новичок в этом.

Я думал о .map над каждым IdLocal и Date, но я не совсем уверен, как бы я это сделал.

Ответы [ 2 ]

1 голос
/ 06 апреля 2020

Во-первых, это очень странный формат даты. Гораздо более распространенным является ISO 8601 , который будет использовать это:

  {IdLocal: 12, Date: "2020-04-06T15:25"},

вместо этого:

  {IdLocal: 12, Date: "04-06-2020T15:25"},

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

const extract = items => Object .values (items .reduce (
  (a, {IdLocal, Date, ...rest}) => {
    const key = IdLocal + ':' + Date.slice(0, 10);
    if (! (key in a) || Date > a [key] .Date) {
      a[key] = {IdLocal, Date, ...rest}
    }
    return a
  }, 
  {}
))

const items = [{IdLocal: 12, Date: '2020-04-06T15:25'}, {IdLocal: 12, Date: '2020-04-06T10:37'}, {IdLocal: 12, Date: '2020-04-05T12:30'}, {IdLocal: 12, Date: '2020-04-05T13:40'}, {IdLocal: 13, Date: '2020-04-06T15:25'}, {IdLocal: 13, Date: '2020-04-06T10:37'}, {IdLocal: 13, Date: '2020-04-05T12:30'}, {IdLocal: 13, Date: '2020-04-05T13:40'}]

console .log (extract (items))
.as-console-wrapper {min-height: 100% !important; top: 0}

Мы используем прямое сокращение в списке, используя ключ, состоящий из переменной IdLocal и части даты метки времени. Он сгенерирует что-то вроде:

{
    "12:2020-04-05": {IdLocal: 12, Date: "2020-04-05T13:40"},
    "12:2020-04-06": {IdLocal: 12, Date: "2020-04-06T15:25"},
    "13:2020-04-05": {IdLocal: 13, Date: "2020-04-05T13:40"},
    "13:2020-04-06": {IdLocal: 13, Date: "2020-04-06T15:25"}
}

, а затем, вызвав Object.values для этого результата, мы получим

[
    {IdLocal: 12, Date: "2020-04-05T13:40"},
    {IdLocal: 12, Date: "2020-04-06T15:25"},
    {IdLocal: 13, Date: "2020-04-05T13:40"},
    {IdLocal: 13, Date: "2020-04-06T15:25"}
]

Обратите внимание на использование расширения в ...rest здесь. Нам нужен определенный c доступ к свойствам IdLocal и Date вашего объекта, но если есть другие, которые вам нужно сохранить, это полезный способ написания кода без пометок item.Date и item.IdLocal везде.

Лично я написал бы это немного по-другому, так как я предпочитаю работать с выражениями, а не с операторами, и я предпочитаю не изменять данные, даже аккумулятор reduce вызовов, если тесты производительности не указывают, что это не так. мутация является узким местом. Так что я мог бы написать это так:

const extract = items => Object .values (items .reduce (
  (a, {IdLocal, Date, ...rest}, _, __, key = IdLocal + ':' + Date.slice(0, 10)) => ({
    ... a,
    [key]: (!a [key] || Date > a[key].Date) ? ({IdLocal, Date, ...rest}) : a [key]
  }), 
  {}
))

Но это та же идея в любой версии.


Если вы застряли в этом формате даты, это не намного сложнее. Я просто ввел функцию, которая будет форматировать дату, а затем использовать ее в нескольких местах:

const formatDate = (d) => `${d.slice(6, 10)}-${d.slice(0, 5)}${d.slice(10)}`

const extract = items => Object .values (items .reduce (
  (a, {IdLocal, Date, ...rest}) => {
    const dateStr = formatDate(Date)
    const key = IdLocal + ':' + dateStr.slice(0, 10)
    if (! (key in a) || dateStr > formatDate (a[key] .Date)) {
      a [key] = {IdLocal, Date, ...rest}
    }
    return a
  },
  {}
))

const items = [{IdLocal: 12, Date: '04-06-2020T15:25'}, {IdLocal: 12, Date: '04-06-2020T10:37'}, {IdLocal: 12, Date: '04-05-2020T12:30'}, {IdLocal: 12, Date: '04-05-2020T13:40'}, {IdLocal: 13, Date: '04-06-2020T15:25'}, {IdLocal: 13, Date: '04-06-2020T10:37'}, {IdLocal: 13, Date: '04-05-2020T12:30'}, {IdLocal: 13, Date: '04-05-2020T13:40'}]

console .log (extract (items))

Это тот же процесс, только что измененный для переформатирования даты для сравнений.

0 голосов
/ 06 апреля 2020

Вы имеете в виду сортировку массива JSON по свойству?

var items = [
  {IdLocal: 12, Date: "04-06-2020T15:25"},
  {IdLocal: 12, Date: "04-06-2020T10:37"},
  {IdLocal: 12, Date: "04-05-2020T12:30"},
  {IdLocal: 12, Date: "04-05-2020T13:40"},
  {IdLocal: 13, Date: "04-06-2020T15:25"},
  {IdLocal: 13, Date: "04-06-2020T10:37"},
  {IdLocal: 13, Date: "04-05-2020T12:30"},
  {IdLocal: 13, Date: "04-05-2020T13:40"}];
  
  function sortByProperty(property){  
    return function(a,b){  
      if(a[property] > b[property])  
         return 1;  
      else if(a[property] < b[property])  
         return -1;  
    return 0;  
    }  
  }
  
  items.sort(sortByProperty("Date")); //sort according to date
  items.reverse();
  
  console.log(items);
  
  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...