从数组中查找每天的第一个和最后一个时间戳



希望有人能帮忙 - 我有一个半小时一次的电表读数数组,需要使用时间戳循环并提取每天的第一个和最后一个电表读数。我有以下格式的数据,时间戳/字符串或 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 ] 
]

是否有力矩功能或替代方法来实现这一点?

感谢您的帮助!

  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>

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

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

更新

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

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

例如

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

这里发生的事情是,它首先使用函数排序将数组从低(第一次读取(到高(最后一次读取(排序(,有关它的更多信息可以在这里找到:https://secure.php.net/manual/en/function.sort.php

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

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

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

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

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

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

自从提出这个问题以来已经有一段时间了,所以我想它已经解决了,无论如何这是我的解决方法,只需要将其形成为 JSON 数组,如果不使用 [0] 代替 .date:

demo.find(element=>
new Date(element.date).getTime() === Math.min(...demo
.map(value=> new Date(value.date).getTime()
))
)

JSFiddle fiddle

相关内容

最新更新