[英]Compare two time objects in D3.js
In D3.js i am currently trying to populate an empty array (array contains only time stamp after every 5 minutes) based on data array contains that time or not . 在D3.js中,我目前正在尝试根据数据数组是否包含该时间来填充一个空数组(数组每5分钟仅包含时间戳记一次)。 If data array contains the time, it should copy the value otherwise null.
如果数据数组包含时间,则应复制值,否则为null。 But when i am trying to compare the two time objects its not working correctly.
但是,当我尝试比较两个时间对象时,它无法正常工作。
Following is the code (the current code is not copying values but printing to make debugging easier): 以下是代码(当前代码不是复制值,而是打印以简化调试):
var data = [{"mytime": "2015-12-01T23:10:00.000Z", "value": 64},
{"mytime": "2015-12-01T23:15:00.000Z", "value": 67},
{"mytime": "2015-12-01T23:20:00.000Z", "value": 70},
{"mytime": "2015-12-01T23:25:00.000Z", "value": 64},
{"mytime": "2015-12-01T23:30:00.000Z", "value": 72},
{"mytime": "2015-12-01T23:35:00.000Z", "value": 75},
{"mytime": "2015-12-01T23:40:00.000Z", "value": 71},
{"mytime": "2015-12-01T23:45:00.000Z", "value": 80},
{"mytime": "2015-12-02T00:00:00.000Z", "value": 80},
{"mytime": "2015-12-02T00:05:00.000Z", "value": 85}
];
var parseDate = d3.time.format("%Y-%m-%dT%H:%M:%S.%LZ").parse;
data.forEach(function(d) {
d.mytime = parseDate(d.mytime);
});
var act_data = [];
var x_extent = d3.extent(data, function(d){
return d['mytime']});
time_arr = d3.time.minute.range(x_extent[0],x_extent[1],5);
for(var key in time_arr){
var temp;
temp = contains(data,time_arr[key],'mytime');
}
function contains(data,value,variable)
{
var i =data.length;
while(i--){
if (data[i][variable] === value)
{
console.log('found');
return i;
}
}
return false;
}
Output should be this: 输出应为:
data = [{"mytime": "2015-12-01T23:10:00.000Z", "value": 64},
{"mytime": "2015-12-01T23:15:00.000Z", "value": 67},
{"mytime": "2015-12-01T23:20:00.000Z", "value": 70},
{"mytime": "2015-12-01T23:25:00.000Z", "value": 64},
{"mytime": "2015-12-01T23:30:00.000Z", "value": 72},
{"mytime": "2015-12-01T23:35:00.000Z", "value": 75},
{"mytime": "2015-12-01T23:40:00.000Z", "value": 71},
{"mytime": "2015-12-01T23:45:00.000Z", "value": 80},
{"mytime": "2015-12-01T23:50:00.000Z", "value": null},
{"mytime": "2015-12-01T23:55:00.000Z", "value": null},
{"mytime": "2015-12-02T00:00:00.000Z", "value": 80},
{"mytime": "2015-12-02T00:05:00.000Z", "value": 85}
];
You can use 您可以使用
d3.time.format
to parse and format your dates d3.time.format
解析和格式化日期 d3.extent
to determine the boundaries of your timestamps d3.extent
确定时间戳的界限 d3.time.scale
to generate the ticks you want to output d3.time.scale
生成要输出的d3.time.scale
d3.map
to hash your input and determine if a value exists d3.map
散列您的输入并确定是否存在值 This gives us 这给了我们
var data = [...];
// for parsing and formatting
var timeformat = d3.time.format("%Y-%m-%dT%H:%M:%S.%LZ");
// range to operate on
var extent = d3.extent(data, function(d){
return timeformat.parse(d.mytime);
});
// scale representing the time stamps
var scale = d3.time.scale()
.domain(extent) // the boundaries
.ticks(d3.time.minute, 5); // 5 minutes intervals
// easier to determine if a value exists
var hashed = d3.map(data, function(d) { return d.mytime; });
// or if your version < 3.5
/*
var hashed = d3.map();
data.forEach(function(d) {
hashed.set(d.mytime, d);
});
*/
// transforms the scale into the desired output
var res = scale.map(function(t) {
var ft = timeformat(t);
return {
mytime: ft,
value: (hashed.has(ft)) ? hashed.get(ft).value : null
};
});
And a demo http://jsfiddle.net/nikoshr/qxcLry8z/ 和一个演示http://jsfiddle.net/nikoshr/qxcLry8z/
var data = [ {"mytime": "2015-12-01T23:10:00.000Z", "value": 64}, {"mytime": "2015-12-01T23:15:00.000Z", "value": 67}, {"mytime": "2015-12-01T23:20:00.000Z", "value": 70}, {"mytime": "2015-12-01T23:25:00.000Z", "value": 64}, {"mytime": "2015-12-01T23:30:00.000Z", "value": 72}, {"mytime": "2015-12-01T23:35:00.000Z", "value": 75}, {"mytime": "2015-12-01T23:40:00.000Z", "value": 71}, {"mytime": "2015-12-01T23:45:00.000Z", "value": 80}, {"mytime": "2015-12-02T00:00:00.000Z", "value": 80}, {"mytime": "2015-12-02T00:05:00.000Z", "value": 85} ]; var timeformat = d3.time.format("%Y-%m-%dT%H:%M:%S.%LZ"); var extent = d3.extent(data, function(d){ return timeformat.parse(d.mytime); }); var scale = d3.time.scale() .domain(extent) .ticks(d3.time.minute, 5); var hashed = d3.map(); data.forEach(function(d) { hashed.set(d.mytime, d); }); var res = scale.map(function(t) { var ft = timeformat(t); return { mytime: ft, value: (hashed.has(ft)) ? hashed.get(ft).value : null }; }); var $table = $('<table></table>'); res.forEach(function(d) { $table.append('<tr><td>'+d.mytime+'</td><td>'+d.value+'</td></tr>') }); $('body').append($table);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
You can do it like this: 您可以这样做:
var extent = d3.extent(data, function(d){ return d.mydate});//get the max min limit
var data1 = []; make an empty array
for (var i =0; i < data.length -1; i++){
var diff = data[i + 1].mytime.getTime() - data[i].mytime.getTime();
if (diff <= 300000){ //less than equal to 5 minutes
data1.push(data[i])
} else { //greater than 5 minutes
var t1 = new Date(data[i].mytime.getTime() + 300000)
var t2 = new Date(data[i +1].mytime.getTime() - 300000)
data1.push({"mytime": t1, "value": null})
data1.push({"mytime": t2, "value": null})
}
}
data1.push(data[data.length -1]); //take the last value as it was not processed
data = data1
With the advent of ES6 there are more options available to tackle the task. 随着ES6的出现,有更多的选项可以解决该任务。 Depending on the browser versions one needs to support, the following code might be a viable approach.
根据需要支持的浏览器版本,以下代码可能是可行的方法。 I have successfully tested this on Chrome 49 and FF 45.
我已经在Chrome 49和FF 45上成功测试了此功能。
The solution adds a custom generator function to the data
array that will return a Generator
object which conforms to the new iteration protocols . 该解决方案将自定义生成器函数添加到
data
数组,该函数将返回符合新迭代协议的Generator
对象。 This will iterate over the data
array and fill in any gaps it detects along the way with objects having their value
property set to null
. 这将遍历
data
数组,并使用其value
属性设置为null
对象填充它检测到的所有间隙。
The snippet further makes use of the spread operator to create a new array and fill it by implicitly invoking the iterator. 该代码段还利用了散布运算符来创建一个新数组,并通过隐式调用迭代器来填充它。
data[Symbol.iterator] = function*() {
var i = 0,
t = this[0],
nextStep;
while (i < this.length) {
nextStep = t.mytime.getTime() + FIVE_MINUTES_IN_MS;
yield t = nextStep < this[i].mytime.getTime()
? {"mytime": new Date(nextStep), "value": null}
: this[i++];
}
};
// use the spread operator to create a new array which will implicitly call
// the iterator
data = [...data];
Have a look at the following snippet for a demo working in Chrome 49 and FF 45: 请查看以下在Chrome 49和FF 45中运行的演示的摘要:
"use strict"; /////////////////////////////////////////////////////////////////////////// // Setup /////////////////////////////////////////////////////////////////////////// const FIVE_MINUTES_IN_MS = 5 * 60 * 1000; var data = [ {"mytime": "2015-12-01T23:10:00.000Z", "value": 64}, {"mytime": "2015-12-01T23:15:00.000Z", "value": 67}, {"mytime": "2015-12-01T23:20:00.000Z", "value": 70}, {"mytime": "2015-12-01T23:25:00.000Z", "value": 64}, {"mytime": "2015-12-01T23:30:00.000Z", "value": 72}, {"mytime": "2015-12-01T23:35:00.000Z", "value": 75}, {"mytime": "2015-12-01T23:40:00.000Z", "value": 71}, {"mytime": "2015-12-01T23:45:00.000Z", "value": 80}, {"mytime": "2015-12-02T00:00:00.000Z", "value": 80}, {"mytime": "2015-12-02T00:05:00.000Z", "value": 85} ]; var parse = d3.time.format("%Y-%m-%dT%H:%M:%S.%LZ").parse; data.forEach(function(d) { d.mytime = parse(d.mytime); }); /////////////////////////////////////////////////////////////////////////// // Implement iterator to fill in gaps in data array /////////////////////////////////////////////////////////////////////////// data[Symbol.iterator] = function*() { var i = 0, t = this[0], nextStep; while (i < this.length) { nextStep = t.mytime.getTime() + FIVE_MINUTES_IN_MS; yield t = nextStep < this[i].mytime.getTime() ? {"mytime": new Date(nextStep), "value": null} : this[i++]; } }; // use the spread operator to create a new array which will implicitly call the iterator data = [...data]; /////////////////////////////////////////////////////////////////////////// // Just output below. /////////////////////////////////////////////////////////////////////////// //console.dir(data); d3.select("body").append("div") .style({ "font-family": "monospace", "white-space": "pre" }) .text(JSON.stringify(data, null, 2));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
Alternatively, you may provide an explicit implementation of the iterator protocol. 或者,您可以提供迭代器协议的显式实现。 This is a little more verbose to write but does not change the overall concept:
这写起来有些冗长,但不会改变整体概念:
data[Symbol.iterator] = function() {
var self = this;
return {
i: 0,
t: self[0],
next() {
if (this.i < self.length) {
var nextStep = this.t.mytime.getTime() + FIVE_MINUTES_IN_MS;
this.t = nextStep < self[this.i].mytime.getTime()
? { "mytime": new Date(nextStep), "value": null }
: self[this.i++];
return {
value: this.t,
done: false
}
} else {
return {
done: true
}
}
}
}
};
The following snippet demonstrates this: 以下代码段演示了这一点:
"use strict"; /////////////////////////////////////////////////////////////////////////// // Setup /////////////////////////////////////////////////////////////////////////// const FIVE_MINUTES_IN_MS = 5 * 60 * 1000; var data = [ {"mytime": "2015-12-01T23:10:00.000Z", "value": 64}, {"mytime": "2015-12-01T23:15:00.000Z", "value": 67}, {"mytime": "2015-12-01T23:20:00.000Z", "value": 70}, {"mytime": "2015-12-01T23:25:00.000Z", "value": 64}, {"mytime": "2015-12-01T23:30:00.000Z", "value": 72}, {"mytime": "2015-12-01T23:35:00.000Z", "value": 75}, {"mytime": "2015-12-01T23:40:00.000Z", "value": 71}, {"mytime": "2015-12-01T23:45:00.000Z", "value": 80}, {"mytime": "2015-12-02T00:00:00.000Z", "value": 80}, {"mytime": "2015-12-02T00:05:00.000Z", "value": 85} ]; var parse = d3.time.format("%Y-%m-%dT%H:%M:%S.%LZ").parse; data.forEach(function(d) { d.mytime = parse(d.mytime); }); /////////////////////////////////////////////////////////////////////////// // Implement iterator to fill in gaps in data array /////////////////////////////////////////////////////////////////////////// data[Symbol.iterator] = function() { var self = this; return { i: 0, t: self[0], next() { if (this.i < self.length) { var nextStep = this.t.mytime.getTime() + FIVE_MINUTES_IN_MS; this.t = nextStep < self[this.i].mytime.getTime() ? { "mytime": new Date(nextStep), "value": null } : self[this.i++]; return { value: this.t, done: false } } else { return { done: true } } } } }; // use the spread operator to create a new array which will implicitly call the iterator data = [...data]; /////////////////////////////////////////////////////////////////////////// // Just output below. /////////////////////////////////////////////////////////////////////////// //console.dir(data); d3.select("body").append("div") .style({ "font-family": "monospace", "white-space": "pre" }) .text(JSON.stringify(data, null, 2));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.