Во-первых, это очень странный формат даты. Гораздо более распространенным является 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))
Это тот же процесс, только что измененный для переформатирования даты для сравнений.