【问题标题】:How to get the latest entry per day from an array in Javascript?如何从Javascript中的数组中获取每天的最新条目?
【发布时间】:2020-07-18 20:55:25
【问题描述】:

嗯,这个问题可能听起来有点奇怪,但我会解释一下。
我在 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,但我不太确定该怎么做。

【问题讨论】:

  • 我认为需要一个更详细的示例。我仍然不明白您在这里通过说“每个本地的每日最新条目”来要求什么类型的日期排序。
  • 好吧,对不起,我觉得它变得混乱了......我的英语不是最好的,但我现在试着让它更容易理解。我认为现在我想要过滤的内容更加明显。我从stackoverflow开始,如果我的问题有任何错误或不符合某些规定,请说,我会尽力解决,谢谢。

标签: javascript arrays node.js date ecmascript-6


【解决方案1】:

第一件事:这是一种非常奇怪的日期格式。更常见的是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 中使用传播。我们需要对对象的 IdLocalDate 属性进行特定访问,但是如果您需要保留其他属性,这是编写代码的有用方法,而不会到处乱扔item.Dateitem.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))

这遵循相同的过程,只是修改为重新格式化日期以进行比较。

【讨论】:

  • 非常感谢,我做了一些修改,非常适合。我会记下 .reduce 的用法,你今天教会了我一些非常有价值的东西:)
【解决方案2】:

您的意思是按属性对 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);
  
  

【讨论】:

  • 完全没有,如果我写的方式让你误解了,我很抱歉......我做了一些编辑,现在它可能更容易理解了。我真正想要的只是每个本地人每天的最新条目。所以第 1 天本地 1 的最新条目,第 2 天本地 1 的最新条目,第 1 天本地 2 的最新条目等等。
  • 我认为你必须为此编写一个函数。首先对日期进行排序,然后遍历数组并获取第一个并跳过其余的,直到日期更改为止。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-22
  • 1970-01-01
  • 1970-01-01
  • 2015-06-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多