Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript object group by day, month, year

I searched over the net, for some examples, haven't find a decent one that works and do the simple task i need, maybe you can help me with it.

I have an array of objects:

[
  {
    "date": "2015-01-01T12:00:00.000Z",
    "photoUrl": "",
    "inProgress": false,
    "isCompleted": true,
    "size": 1024
  },
  {
    "date": "2015-01-02T12:00:00.000Z",
    "photoUrl": "",
    "inProgress": false,
    "isCompleted": false,
    "size": 1024
  },
  {
    "date": "2015-02-01T12:00:00.000Z",
    "photoUrl": "",
    "inProgress": true,
    "isCompleted": false,
    "size": 1024
  },
  {
    "date": "2015-02-02T12:00:00.000Z",
    "photoUrl": "",
    "inProgress": false,
    "isCompleted": true,
    "size": 1024
  },
  {
    "date": "2016-04-01T12:00:00.000Z",
    "photoUrl": "",
    "inProgress": true,
    "isCompleted": false,
    "size": 1024
  },
  {
    "date": "2016-04-02T12:00:00.000Z",
    "photoUrl": "",
    "inProgress": false,
    "isCompleted": true,
    "size": 1024
  }
] 

I'm looking for a simple straight forward solution to group them by year, then by month, then by day in the following way

The result should be something that i can iterate on like the following:

[
  {
    "2015": [
      {
        "JAN": [
          {
            "01": {
              "date": "2015-01-01T12:00:00.000Z",
              "photoUrl": "",
              "inProgress": false,
              "isCompleted": true,
              "size": 1024
            },
            "02": {
              "date": "2015-01-01T12:00:00.000Z",
              "photoUrl": "",
              "inProgress": false,
              "isCompleted": true,
              "size": 1024
            }
          }
        ],
        "FEB": [
          {
            "01": {
              "date": "2015-02-01T12:00:00.000Z",
              "photoUrl": "",
              "inProgress": false,
              "isCompleted": true,
              "size": 1024
            },
            "02": {
              "date": "2015-02-02T12:00:00.000Z",
              "photoUrl": "",
              "inProgress": false,
              "isCompleted": true,
              "size": 1024
            }
          }
        ]
      },
    ],
    "2016": [
      {
        "APR": [
          {
            "02": {
              "date": "2016-04-02T12:00:00.000Z",
              "photoUrl": "",
              "inProgress": false,
              "isCompleted": true,
              "size": 1024
            }
          }
        ]
      }
    ]
  }
]

The final purpose is to go over it in a list by ng-repeat with angular.

If anyone have a suggestion i'm sure this code will be very usuefull to other, cause there are no example of taking flat array of dates and convert it to an object of year, month and day, anywhere over the net.

Thanks a Lot!

like image 369
Liad Livnat Avatar asked Apr 08 '26 07:04

Liad Livnat


2 Answers

You could just check if year is set and if not the assign an array with an empty object in it. Then proceed with the month and later assign the item to it.

var data = [{ date: "2015-01-01T12:00:00.000Z", photoUrl: "", inProgress: false, isCompleted: true, size: 1024 }, { date: "2015-01-02T12:00:00.000Z", photoUrl: "", inProgress: false, isCompleted: false, size: 1024 }, { date: "2015-02-01T12:00:00.000Z", photoUrl: "", inProgress: true, isCompleted: false, size: 1024 }, { date: "2015-02-02T12:00:00.000Z", photoUrl: "", inProgress: false, isCompleted: true, size: 1024 }, { date: "2016-04-01T12:00:00.000Z", photoUrl: "", inProgress: true, isCompleted: false, size: 1024 }, { date: "2016-04-02T12:00:00.000Z", photoUrl: "", inProgress: false, isCompleted: true, size: 1024 }],
    grouped = Object.create(null);

data.forEach(function (a) {
    var year = a.date.slice(0, 4),
        month = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'][a.date.slice(5, 7) - 1],
        day = a.date.slice(8, 10);

    grouped[year] = grouped[year] || [{}];
    grouped[year][0][month] = grouped[year][0][month] || [{}];
    grouped[year][0][month][0][day] = a;
});

console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
like image 52
Nina Scholz Avatar answered Apr 09 '26 20:04

Nina Scholz


Unfortunately, there doesn't seem to be a way to reduce this further as each level has different key/value requirements.

var data = [{"date":"2015-01-01T12:00:00.000Z","photoUrl":"","inProgress":false,"isCompleted":true,"size":1024},{"date":"2015-01-02T12:00:00.000Z","photoUrl":"","inProgress":false,"isCompleted":false,"size":1024},{"date":"2015-02-01T12:00:00.000Z","photoUrl":"","inProgress":true,"isCompleted":false,"size":1024},{"date":"2015-02-02T12:00:00.000Z","photoUrl":"","inProgress":false,"isCompleted":true,"size":1024},{"date":"2016-04-01T12:00:00.000Z","photoUrl":"","inProgress":true,"isCompleted":false,"size":1024},{"date":"2016-04-02T12:00:00.000Z","photoUrl":"","inProgress":false,"isCompleted":true,"size":1024  }];
var months = [,"JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"];
var re = /^(\d{4})-(\d{2})-(\d{2})/;
var results = data.reduce(function(results,value){
  var date = value.date.match(re);
  var temp = results;
  var key = date[1];
  if(!temp.hasOwnProperty(key)) temp[key] = {};
  temp = temp[key];
  key = months[date[2]|0];
  if(!temp.hasOwnProperty(key)) temp[key] = {};
  temp = temp[key];
  key = date[3];
  if(!temp.hasOwnProperty(key)) temp[key] = [];
  temp = temp[key];
  
  temp.push(value);
  return results;
},{});
console.log(results);
.as-console-wrapper { max-height: 100% !important; top: 0; }
like image 21
Ouroborus Avatar answered Apr 09 '26 19:04

Ouroborus



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!