Liad Livnat
Liad Livnat

Reputation: 7475

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!

Upvotes: 3

Views: 1254

Answers (2)

Nina Scholz
Nina Scholz

Reputation: 386560

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; }

Upvotes: 2

Ouroborus
Ouroborus

Reputation: 16875

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; }

Upvotes: 1

Related Questions