-1

There is an object array like this:

[
  {
    timestamp: 1318781876
    any: 'other fields'
  }
]

Of course there are multiple objects in that array. I am using momentJS - if it matters here...

Now I need to split that array into months. That means I need to get all objects for 'july' to display them in a table. Is this possible at all or should I change the datastructure? I thought using timestamp is the best option, as I could calculate everything from this.

But now I'm thinking if I have to add month and year field to the object...

user3142695
  • 15,844
  • 47
  • 176
  • 332
  • Pretty sure with this format you'd have to iterate over all of them. Is it possible to just include Month/Year/Day in the object itself? – jdmdevdotnet Jul 28 '17 at 17:08
  • 2
    if you are trying to save on payload size transmitted, you should not include the month as a separate key, as the raw timestamp can be leveraged. – jagzviruz Jul 28 '17 at 17:19
  • 1
    and as you pointed out yourself: one can easily calculate the year / month based from that. Storing year / month inside the database increases storage + transmition volume a lot, without a big performance inprovement.. – Jonas Wilms Jul 28 '17 at 17:33

5 Answers5

2

You could iterate the array and build up a tree, may also write year and month to the objects:

var map={};

array.forEach(function(obj){
 var d = new Date(obj.timestamp*1000);
 var m = obj.month = d.getMonth() +1;
 var y = obj.year = d.getFullYear();

  if(!map[y]) map[y]={};
  if(!map[y][m]) map[y][m]=[];

  map[y][m].push(obj);
});

So now weve got a map like this:

map: {
  2017 : {
   8 : [
    {
      timestamp:123456,
      month:8,
      year:2017,
      any:"other value"
    }
  ]
}
}

So you can now get all julys by:

map[2017][7]

It depends if you just do this once, then other answers will be easier, but if you need different timeranges the upper code just needs to iterate once, and you can get the filtered results easily. To get sorted results:

var sorted=Object.keys(map)/*the years*/ .sort().map(function(year){
  return { year, months: Object.keys(map[year]).sort().map(function(month){
    return {month,results:map[year][month]};
  })
 };
});

These arrays may already be built up while building the hash table, see ninas way of doing this

Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • 1
    filter is way simpler. – jdmdevdotnet Jul 28 '17 at 17:10
  • 1
    Depending on your need. If you need the whole tree that could be the better option. However @Jonas it seems like the timestamp is in seconds, not ms, and therefore needs to get multiplied by 1000. – Stephan Jul 28 '17 at 17:11
  • @jdmdevdotnet yes shure. But if you want the user be able to e.g. *get results by month* you just run the upper code once, after that you just need to display the small sub arrays. – Jonas Wilms Jul 28 '17 at 17:14
  • 1
    @Jonasw touche. – jdmdevdotnet Jul 28 '17 at 17:15
  • @Jonasw I like that approach, as I need to process all data later, so I do get better access to every subdataset. But I need to process the data in ascending order, and your result map doesn't have a order. I need to process first all 2016 data, then 2017; within those I also need to process the months in ascending order. How can I achieve this? – user3142695 Jul 28 '17 at 18:21
1

This can be done using array.filter

myArr = [
  {
    timestamp: 1318781876
    any: 'other fields'
  }
  ...
];

var filteredArray = myArr.filter(function(item) {
  return (item.timestamp > minOfDateRange && item.timestamp < maxOfDateRange);
});
ControlAltDel
  • 33,923
  • 10
  • 53
  • 80
  • @jdmdevdotnet I'm sorry about that. It happened because I was actually correcting another issue. Your edit was good and useful, and I've incorporated it now – ControlAltDel Jul 28 '17 at 17:12
1

Your structure is quite useful. You can use Array.filter:

const startDate = new Date(2017, 6, 1); // 6 for July
const endDate = new Date(2017, 7, 1);
const selectedData = data.filter(entry => startDate <= entry.timestamp * 1000 && entry.timestamp * 1000 < endDate)
Stephan
  • 2,028
  • 16
  • 19
0

Convert the milisecond to a date using following code and get the month afterward

var date = new Date(milliseconds); var month = date.getMonth();

then put the july object to another array and display them as you wish

0

You can use a hashmap approach.

var arr = [
...
{
    timestamp: 1318781876
    any: 'other fields'
  }
...
];

var grouped = {};
var months = ['Jan', 'Feb' ...];
arr.forEach( function(item){
  var dateObj = moment.unix(item.timestamp);
  var month = months[dateObj.month()];
  if(!grouped[month]){
    grouped[month] = [];
  }
  grouped[month].push(item);
});

console.log(grouped);
jagzviruz
  • 1,453
  • 12
  • 27