简体   繁体   中英

In javascript, how do I create a nested array or object from json data?

This is a modification of a previously asked question ( In javascript, how do I extract the month from date string "yyyy-mm-dd" or timeStamp? ), which was solved nicely by @mhodges.

Because of the nature of the modification, I thought it would be appropriate to just create a new question.

I have a database with certain logged events as json objects, each one with it's own JS millisecond timestamp and also a date string in the format "yyyy-mm-dd", as well as a minutes entry.

I'd like to use the timestamp as input into an algorithm which will count how many logs were entered in a given month and year.

I would also like the algorithm to sum the cumulative number of minutes were logged in a given month and year.

For example,

log1: {
    Date:"2017-05-24",
    TimeStamp:1495612800,
    Minutes: 15},
log2: {
    Date:"2017-05-19",
    TimeStamp:1495180800,
    Minutes: 45},
log3: {
    Date:"2017-04-24",
    TimeStamp:1493020800,
    Minutes:30},
log4: {
    Date:"2016-08-15",
    TimeStamp:1471248000,
    Minutes:75}

In this example, the algorithm would count that there are two logs in the month of May 2017, one log in the month of April 2017 and one log in the month of August 2016.

The algorithm would also return a sum of 60 minutes in the month of May 2017, 30 minutes in the month of April 2017 and 75 minutes in August 2016.

Any help with modifying the solution that @mhodges provided previously (see ( In javascript, how do I extract the month from date string "yyyy-mm-dd" or timeStamp? )), into the appropriate nested output would be greatly appreciated!

I am having trouble modifying @mhodges solution to achieve it, but envision something like this:

{
  "2016":{
    "8": {
      occurrences: 1,
      minutes: 75
    }
  },
  "2017":{
    "4": {
      occurrences: 1,
      minutes: 30
    },
    "5": {
      occurrences: 2,
      minutes: 60
    }
  }
}

Thanks

Seems like a good problem to solve with the Array.prototype.map and Array.prototype.reduce as well as some of the built in Date methods.

 const logs = [ { Date:"2017-05-24", TimeStamp:1495612800, Minutes: 15 }, { Date:"2017-05-19", TimeStamp:1495180800, Minutes: 45 }, { Date:"2017-04-24", TimeStamp:1493020800, Minutes:30 }, { Date:"2016-08-15", TimeStamp:1471248000, Minutes:75 }] // mapping over the logs, transforming each so that we have data in the right form (ie. years, months, and minutes; occurences we'll get later). const flat = logs.map(log => { const date = new Date(log.Date) return { year: date.getFullYear(), month: date.getMonth() + 1, minutes: log.Minutes, } }) const hierarchy = flat.reduce((hier, log) => { // As we're building the result, we need to init things if they don't already exist hier[log.year] = hier[log.year] || {} // The lowest level will have this form hier[log.year][log.month] = hier[log.year][log.month] || { occurences: 0, minutes: 0 } // Accumulate minutes and occurences as we go hier[log.year][log.month].minutes += log.minutes hier[log.year][log.month].occurences += 1 return hier }, {}) console.log(hierarchy) 

Judging from your expected output, you probably want to use the date value instead of timestamp. You could loop through the logs and add up the minutes for each month.

It would look something like this:

 var logs = [{ Date: "2017-05-24", TimeStamp: 1495612800, Minutes: 15 }, { Date: "2017-05-19", TimeStamp: 1495180800, Minutes: 45 }, { Date: "2017-04-24", TimeStamp: 1493020800, Minutes: 30 }, { Date:"2016-08-15", TimeStamp:1471248000, Minutes:75 } ]; var result = {}; for (var i = 0; i < logs.length; i++) { var year = logs[i].Date.slice(0, 4); var month = logs[i].Date.slice(5, 7); if (!result[year]) { result[year] = {}; } if (!result[year][month]) { result[year][month] = { occurences: 1, minutes: logs[i].Minutes } continue; } result[year][month].occurences++; result[year][month].minutes += logs[i].Minutes; } console.log(result); 

Here's a crack at it.

let i = arr.length;
let obj = {};
while(i--){
  let [year, month, day] = arr[i].Date.split('-');

  //probably a better way of initializing a hashtree.
  if(!obj[year]){ obj[year] = {}; } 
  if(!obj[year][month]){ obj[year][month] = {}}

  let occur = obj[year][month]['occurences'] 
  let minutes = obj[year][month]['minutes'] 

  obj[year][month]['occurences'] = (occur === undefined) ? 1 : occur + 1;
  obj[year][month]['minutes'] = (minutes === undefined) ? arr[i].Minutes : arr[i].Minutes + minutes;
}

https://jsfiddle.net/25n4jo4e/

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