这个问题可能听起来有点奇怪,但我会解释一下。
我有一个 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))
这遵循相同的过程,只是进行了修改以重新格式化日期以进行比较。
关于javascript - 如何从 Javascript 数组中获取每天的最新条目?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61066925/