【问题标题】:JS: Get objects from array within a time rangeJS:在时间范围内从数组中获取对象
【发布时间】:2017-07-28 17:03:30
【问题描述】:

有一个像这样的对象数组:

[
  {
    timestamp: 1318781876
    any: 'other fields'
  }
]

当然,该数组中有多个对象。我正在使用momentJS - 如果这很重要......

现在我需要将该数组拆分为几个月。这意味着我需要获取“七月”的所有对象以将它们显示在表格中。 这完全可能还是我应该更改数据结构?我认为使用时间戳是最好的选择,因为我可以从中计算出所有内容。

但现在我在考虑是否必须将month 和year 字段添加到对象...

【问题讨论】:

  • 很确定使用这种格式,您必须遍历所有这些格式。是否可以只在对象本身中包含月/年/日?
  • 如果您尝试节省传输的有效负载大小,则不应将月份作为单独的键包含,因为可以利用原始时间戳。
  • 正如您自己指出的那样:您可以根据此轻松计算年/月。在数据库中存储年/月会大大增加存储量+传输量,而性能没有很大的提升..

标签: javascript arrays momentjs


【解决方案1】:

您可以迭代数组并构建一棵树,也可以将年份和月份写入对象:

var map={};

array.forEach(function(obj){
 var d = new Date(obj.timestamp*1000);
 var m = obj.month = d.getMonth() +1;
 var y = obj.year = d.getFullYear();

  if(!map[y]) map[y]={};
  if(!map[y][m]) map[y][m]=[];

  map[y][m].push(obj);
});

所以现在我们得到了这样的地图:

map: {
  2017 : {
   8 : [
    {
      timestamp:123456,
      month:8,
      year:2017,
      any:"other value"
    }
  ]
}
}

所以你现在可以通过以下方式获得所有的七月:

map[2017][7]

这取决于您是否只执行一次,然后其他答案会更容易,但是如果您需要不同的时间范围,则上面的代码只需迭代一次,您就可以轻松获得过滤后的结果。要获得排序结果:

var sorted=Object.keys(map)/*the years*/ .sort().map(function(year){
  return { year, months: Object.keys(map[year]).sort().map(function(month){
    return {month,results:map[year][month]};
  })
 };
});

这些数组可能在构建哈希表时已经建立,请参阅ninas way of doing this

【讨论】:

  • 过滤器更简单。
  • 取决于您的需要。如果您需要整棵树,那可能是更好的选择。但是@Jonas 似乎时间戳以秒为单位,而不是毫秒,因此需要乘以 1000。
  • @jdmdevdotnet 是的,舒尔。但是,如果您希望用户能够例如按月获取结果你只需要运行上面的代码一次,然后你只需要显示小的子数组。
  • @Jonasw touche.
  • @Jonasw 我喜欢这种方法,因为我需要稍后处理所有数据,所以我确实可以更好地访问每个子数据集。但是我需要按升序处理数据,而你的结果图没有顺序。我需要首先处理所有 2016 年的数据,然后是 2017 年;在这些中,我还需要按升序处理月份。我怎样才能做到这一点?
【解决方案2】:

这可以使用 array.filter 来完成

myArr = [
  {
    timestamp: 1318781876
    any: 'other fields'
  }
  ...
];

var filteredArray = myArr.filter(function(item) {
  return (item.timestamp > minOfDateRange && item.timestamp < maxOfDateRange);
});

【讨论】:

  • @jdmdevdotnet 对此我很抱歉。发生这种情况是因为我实际上是在纠正另一个问题。您的编辑很好且有用,我现在已将其合并
【解决方案3】:

你的结构很有用。你可以使用Array.filter:

const startDate = new Date(2017, 6, 1); // 6 for July
const endDate = new Date(2017, 7, 1);
const selectedData = data.filter(entry => startDate <= entry.timestamp * 1000 && entry.timestamp * 1000 < endDate)

【讨论】:

    【解决方案4】:

    使用以下代码将毫秒转换为日期并获取之后的月份

    var date = new Date(毫秒); var month = date.getMonth();

    然后将 july 对象放到另一个数组中并根据需要显示它们

    【讨论】:

      【解决方案5】:

      您可以使用 hashmap 方法。

      var arr = [
      ...
      {
          timestamp: 1318781876
          any: 'other fields'
        }
      ...
      ];
      
      var grouped = {};
      var months = ['Jan', 'Feb' ...];
      arr.forEach( function(item){
        var dateObj = moment.unix(item.timestamp);
        var month = months[dateObj.month()];
        if(!grouped[month]){
          grouped[month] = [];
        }
        grouped[month].push(item);
      });
      
      console.log(grouped);
      

      【讨论】:

      • 假设您的时间戳以秒为单位 .. 对于毫秒,您可以使用 moment(item.timestamp)
      • 你不想 map ,你只想用 forEach 迭代
      • 仅用于计算时间戳的月份不需要使用 Moment.js。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-12
      • 2021-06-09
      • 1970-01-01
      • 2014-07-23
      • 2021-01-10
      相关资源
      最近更新 更多