简体   繁体   中英

Fill missing dates in json string with jquery/javascript

Here's a sample of what I have:

[{
  "probeTemp": "35.40",
  "dateProbe": "2015-08-1"
}, {
  "probeTemp": "34.89",
  "dateProbe": "2015-08-3"
}, {
  "probeTemp": "34.42",
  "dateProbe": "2015-08-5"
}]

How can I fill the missing dates between the min and max dates in the json string so the missing fields end up like this?

    [{
      "probeTemp": "35.40",
      "dateProbe": "2015-08-1"
    }, {
      "probeTemp": null,
      "dateProbe": "2015-08-2"
    }, {
      "probeTemp": "34.89",
      "dateProbe": "2015-08-3"
    }, {
      "probeTemp": null,
      "dateProbe": "2015-08-4"
    }, {
      "probeTemp": "34.42",
      "dateProbe": "2015-08-5"
    }]

I found this thread , but I don't know how I could apply it to my data. Any help?

Edit 2: This is what I tried so far , but I'm getting Uncaught TypeError: Cannot read property 'length' of undefined at lines 7 and 23.

Hey i would do somethink like this.

  1. Fetch the first Date and parse ist Date.parse()
  2. walk to the next Date, check if the first date + 1 (new Date()getDate() + 1) is the same Date, if so walk next if not creating this Date and inserting it.
  3. And so on

Instantiate a Date using the api here which is smart enough to - when advanced a day at a time in an iteration - account for short months, leap years, etc. Advance by adding 1 to whatever the getDate() returns (on the Date instance) and then call the setDate method with that later value. Or add the number of milliseconds in a day using the getTime and setTime methods.

Check each date against your previously existing map of probe temperatures

You can have another instance of the max date lying in wait for comparison. Use the getTime method on both instances when doing your comparisons, ie:

if ( iterDate.getTime() !== maxDate.getTime() ) {
    if ( !previousProbeTemp )
        newProbeTemp = null;

We starts from getting first and last dates. Let

const a = [{
  "probeTemp": "35.40",
  "dateProbe": "2015-08-1"
}, {
  "probeTemp": "34.89",
  "dateProbe": "2015-08-3"
}, {
  "probeTemp": "34.42",
  "dateProbe": "2015-08-5"
}]; 

Then

const firstDate = a[0].dateProble; // "2015-08-1"
const lastDate = a[a.length-1].dateProbe; // "2015-08-5"

Now we can build range of all dates.

const dates = [ ...Array(
        Date.parse(lastDate)/86400000 - Date.parse(firstDate)/86400000 + 1).keys()    
    ].map(k => new Date(
            86400000*k+Date.parse(firstDate)
        ).toISOString().slice(0, 10).replace(/-0(\d)$/, '-$1')); 
// [ "2015-08-1", "2015-08-2", "2015-08-3", "2015-08-4", "2015-08-5" ] 

We created range with proper length, then moved it in timeline by number of milliseconds from epoch to first of dates. Finally we created Dates again transform to strings, sliced to get more natural format of dates and use regexp to remove leading 0 from number of days.

In last step we can define res - variable that contain our results. We define it as empty array and in for loop pushing next elements. Most important is probeTemp . If date that we considering from our range is equal date from array then we can add probeTemp and then increment j index, if it is new date than probeTemp is equall null and j index is not changed.

let res = []; 
for(let i=0,j=0; i<dates.length; i++) { 
    res[i] = {
        dateProbe: dates[i], 
        probeTemp: dates[i] === a[j].dateProbe ? a[j++].probeTemp : null
    }; 
}; 
console.table(res);

This solution works for sorted array a .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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