Find the first & last timestamp for each day from an array of arrays

时间:2018-10-02 09:18:19

标签: javascript arrays momentjs

Hope someone can help - I have an array of half-hourly energy meter readings and need to loop through and extract the first and last meter reading each day using the timestamps. I have the data in the following formats, either timestamp/string or unix/milliseconds - its a large array covering several months.

[ 
 [ '2018-09-10 22:51:53', 258.707 ],
 [ '2018-09-10 23:21:55', 258.707 ],
 [ '2018-09-10 23:51:56', 258.707 ],
 [ '2018-09-11 00:21:57', 258.707 ],
 [ '2018-09-11 00:51:59', 258.707 ] 
]

OR

[ 
 [ 1536623513000, 258.707 ],
 [ 1536625315000, 258.707 ],
 [ 1536627116000, 258.707 ],
 [ 1536628917000, 258.707 ],
 [ 1536630719000, 258.707 ] 
]

Is there a moment function or alternative way to achieve this?

Thanks for your help!

6 个答案:

答案 0 :(得分:1)

更新

将代码示例从PHP转换为JavaScript-我之前自欺欺人。

var result = {}, item, stamp, reading;
while(data.length)
{
  // we do not care about the order of the items
  item = data.pop();
  stamp = item[0];
  reading = item[1];

  // get the date only, strip the time
  if(typeof stamp !== 'number') stamp = stamp.substr(0, 10);
  else stamp = (new Date(stamp)).toISOString().substr(0, 10);

  item = result[stamp];
  if(item)
  {
    if(reading < item[0]) item[0] = reading;
    else if(reading > item[1]) item[1] = reading;
  }
  // this date was not seen before
  else result[stamp] = [reading, reading]; // MIN and MAX are the same
}

对于原始数组中的每个项目-您都为给定日期创建一个存储桶,并更新该日期的MIN和MAX值。

答案 1 :(得分:1)

这是我在评论中提到的解决方案:

  1. 过滤数组以单独查看每天
  2. 整理每天的元素
  3. 获取日期数组的第一个和最后一个元素

代码示例:

const data = [
  ['2018-09-10 22:51:53', 258.707],
  ['2018-09-10 23:21:55', 259.707],
  ['2018-09-10 23:51:56', 259.907],
  ['2018-09-11 00:21:57', 260.101],
  ['2018-09-11 00:51:59', 260.102]
];

const monthfilter = month => datestring => new Date(datestring[0]).getMonth() === month;
const datefilter = date => datestring => new Date(datestring[0]).getDate() === date;

// filter by month first so sorting is optimized
for (var month = 0; month < 12; month++) {
  var monthdata = data.filter(monthfilter(month)).sort((a, b) => a > b);
  // go through each day of the month
  for (var date = 1; date <= 30; date++) { // 30 days is just for september example!
    // grab day data
    var tmp = monthdata.filter(datefilter(date));
    if (tmp.length === 0) continue;
    print(tmp[0][0], tmp[0][1], tmp.pop()[1]);
  }
}

function print(datestring, first, last) {
  var date = new Date(datestring).toISOString().substring(0, 10);
  console.log(`${date}: ${first} - ${last}\n`);
}

答案 2 :(得分:1)

  1. 按日期对元素进行分组
  2. 找到每个日期集合的最小和最大

var demo = [ 
 [ '2018-09-10 22:51:53', 258.3 ],
 [ '2018-09-10 23:21:55', 258.2 ],
 [ '2018-09-10 23:51:56', 258.5 ],
 [ '2018-09-11 00:21:57', 258.7027 ],
 [ '2018-09-11 00:51:59', 251.707 ] 
];


let grouped_items = _.groupBy(demo, function(b) {
  return moment(b[0]).format('YYYY-MM-DD');
});

  Object.keys(grouped_items).forEach(function(item) {
    grouped_items[item] = findMinMax( grouped_items[item]);
});


function findMinMax(item){
   var res = {min: item[0][1], max:item[0][1]};
  
  item.forEach(function(val) {
    res.min = val[1] < res.min ? val[1] :res.min;
    res.max = val[1] > res.max ? val[1] :res.max;
});
  
  return res;
}

console.log(grouped_items);
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.1/moment.min.js"></script>
  
  <title>JS Bin</title>
</head>
<body>

</body>
</html>

答案 3 :(得分:0)

一种实现此目的的方法是对数组进行排序,然后获取第一个和最后一个索引。

例如

sort($your_array);
$first_reading=$your_array[0];
$last_index=count($your_array)-1;
$last_reading=$your_array[$last_index];

这里发生的是,它首先使用函数sort将数组从低(第一读)到高(最后读)进行排序,有关此的更多信息,请参见:https://secure.php.net/manual/en/function.sort.php

然后,您将获得带有函数count的数组中的最后一个元素,该函数将计算数组中有多少个元素。确保从该计数中减去1,因为数组的索引从0开始(而计数从1开始)。

edit:更多数组排序功能可以在这里找到: https://secure.php.net/manual/en/array.sorting.php 如果您想用钥匙或其他东西来排序。

答案 4 :(得分:0)

您可以使用moment()。dayOfYear()函数(http://momentjs.com/docs/#/get-set/day-of-year/)来检查日期属于哪一天,然后可以比较valueOf()(http://momentjs.com/docs/#/displaying/unix-timestamp-milliseconds/)来查看哪个日期是第一个和最后一个。

如果您的日期跨越多年,则可以另外检查年份。

答案 5 :(得分:-1)

我不确定嵌套数组结构最适合处理此类数据。改为使用数组内的对象,将日期与可以过滤的属性相关联,是否可行?

如果要使用嵌套数组,我认为您首先必须解决将日期和时间转换为可以使用比较运算符轻松评估的格式的问题。您可以遍历数组中的每个条目,并将日期返回为月份中的日期(因此,2018-09-10上的所有条目都将返回数字10,依此类推),并返回以毫秒为单位的时间(自1月起) 1970年1月1日)。像这样:

    var dates = [ 
 [ '2018-09-10 22:51:53', 258.707 ],
 [ '2018-09-10 23:21:55', 258.707 ],
 [ '2018-09-10 23:51:56', 258.707 ],
 [ '2018-09-11 00:21:57', 258.707 ],
 [ '2018-09-11 00:51:59', 258.707 ] 
]

dates.forEach(day => {
              var date = new Date(day[0]);
              var newDay = date.getDate();
              var newTime = date.getTime()
              console.log(newDay);
              console.log(newTime);
          });