这个问题听起来可能有点奇怪,但我会解释的
我在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
]
正如你所看到的,我希望它每天只返回每个本地人的最新条目。
我认为,如果返回的数组变得巨大,那么反复迭代我的数组可能会非常昂贵
我知道现代Javascript有.map和.filter等非常有用的数组方法,但我是它的创建者。
我在想每个IdLocal和Date的.map,但我真的不确定该怎么做。
首先:这是一种非常奇怪的日期格式。更常见的是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
中使用扩频。我们需要对对象的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))
这遵循相同的过程,只是修改为重新格式化日期以进行比较。
您的意思是按属性对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);