【问题标题】:Find the first & last timestamp for each day from an array of arrays从数组数组中查找每天的第一个和最后一个时间戳
【发布时间】:2018-10-02 09:18:19
【问题描述】:

希望有人能提供帮助 - 我有一组每半小时一次的电能表读数,需要使用时间戳循环并提取每天的第一个和最后一个电表读数。我有以下格式的数据,时间戳/字符串或 unix/毫秒 - 它是一个涵盖几个月的大型数组。

[ 
 [ '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 ] 
]

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

有没有矩函数或替代方法来实现这一点?

感谢您的帮助!

【问题讨论】:

  • 您可以过滤数组使其仅包含一天,然后只需获取第一个和最后一个元素。
  • 谢谢克里斯,这种方法也可以,但仍然需要过滤测试来识别每天的第一个或最后一个时间戳 - 有什么想法吗?
  • 过滤后,按日期对数组进行排序,然后抓取第一个和最后一个元素。

标签: javascript arrays momentjs


【解决方案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>

【讨论】:

  • 感谢 Alessio,这个解决方案非常适合我的需求,让我能够提取我需要的所有数据 - 干杯!
  • 如果您认为答案是正确的,您可以接受它,也许它可以对其他用户有用。 meta.stackexchange.com/questions/5234/…
【解决方案2】:

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

  1. 过滤数组以分别查看每一天
  2. 对每天的元素进行排序
  3. 获取 day 数组的第一个和最后一个元素

代码示例:

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`);
}

【讨论】:

    【解决方案3】:

    更新

    将代码示例从 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 值。

    【讨论】:

    • 据我所知,OP 没有提到 PHP anywhere
    【解决方案4】:

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

    例如

    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 开始)。

    编辑:更多数组排序函数可以在这里找到: https://secure.php.net/manual/en/array.sorting.php 如果您想使用键或其他东西进行排序。

    【讨论】:

    • 感谢 hortig,我不熟悉 PHP,但我相信这对其他人有用。
    【解决方案5】:

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

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

    【讨论】:

    • 感谢 WhiteMaple - 我喜欢这个想法,认为它可以工作 - 干杯。
    【解决方案6】:

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

    如果您想使用嵌套数组,我认为您首先必须解决将日期和时间转换为可以使用比较运算符轻松评估的格式的问题。您可以遍历数组中的每个条目,并将日期作为月份中的某天返回(因此 2018-09-10 上的所有条目都将返回数字 10,依此类推)和时间作为毫秒数(从 1 月开始1970 年第 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);
              });
    

    【讨论】:

    • 嗨,Eric,数据是以 JSON 格式获取的,所以以对象格式开始,我提取到一个数组中以供其他地方使用,但我认为你是对的,这将是一种更简单的方法 - 谢谢。
    • 这不是答案。
    猜你喜欢
    • 1970-01-01
    • 2018-04-22
    • 2022-09-24
    • 1970-01-01
    • 1970-01-01
    • 2021-06-01
    • 1970-01-01
    • 2014-10-25
    • 1970-01-01
    相关资源
    最近更新 更多