简体   繁体   English

比较D3.js中的两个时间对象

[英]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 您可以使用

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

working code here 这里的工作代码

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM