在D3.js中我正在尝试填充一个空数组(数组每5分钟后只包含时间戳),基于数据数组包含该时间。如果数据数组包含时间,则应复制该值,否则为null。但是,当我试图比较两个时间对象时,它无法正常工作。
以下是代码(当前代码不是复制值而是打印以使调试更容易):
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;
}
输出应为:
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}
];
答案 0 :(得分:3)
您可以使用
d3.time.format
用于解析和格式化您的日期d3.extent
确定时间戳的边界d3.time.scale
生成您要输出的刻度d3.map
哈希输入并确定值是否存在这给了我们
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
};
});
演示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);
&#13;
<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>
&#13;
答案 1 :(得分:1)
你可以这样做:
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
工作代码here
答案 2 :(得分:0)
随着ES6的出现,可以使用更多选项来解决这个问题。根据需要支持的浏览器版本,以下代码可能是一种可行的方法。我已经在Chrome 49和FF 45上成功测试了这个。
该解决方案会向data
数组添加一个自定义generator function,该数组将返回符合新Generator
的iteration protocols对象。这将遍历data
数组并填充它在value
属性设置为null
的对象时检测到的任何间隙。
该代码段进一步利用spread operator创建一个新数组,并通过隐式调用迭代器来填充它。
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];
请查看以下代码片段,了解在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));
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
&#13;
或者,您可以提供iterator协议的显式实现。这写起来有点冗长,但并没有改变整体概念:
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 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));
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
&#13;