1

I have a requirement to group an array of objects based on time interval. The input looks like:

[
  {
    _id: {
      hour: 0,
      interval: '0'
    },
    time: '0:0',
    count: 10
  },
  {
    _id: {
      hour: 0,
      interval: '15'
    },
    time: '0:15',
    count: 5
  },
  {
    _id: {
      hour: 0,
      interval: '30'
    },
    time: '0:30',
    count: 1
  },
  {
    _id: {
      hour: 0,
      interval: '45'
    },
    time: '0:45',
    count: 2
  },
  {
    _id: {
      hour: 1,
      interval: '0'
    },
    time: '1:0',
    count: 4
  },
  {
    _id: {
      hour: 1,
      interval: '15'
    },
    time: '1:15',
    count: 3
  },
  {
    _id: {
      hour: 1,
      interval: '30'
    },
    time: '1:30',
    count: 5
  },
  {
    _id: {
      hour: 1,
      interval: '45'
    },
    time: '1:45',
    count: 1
  }
]

My desired output:

[
      {
        "time": "0",
        "0": 10,
        "15": 5
        "30": 1,
        "45": 2
      },
      {
        "time": "1",
        "0": 4,
        "15": 3
        "30": 5,
        "45": 1
      }
    ]

I tried to use the following code to group the objects, which works to an extent, but I'm stuck on what to do next:

const a = [ { _id: { hour: 0, interval: '0' }, time: '0:0', count: 10 }, { _id: { hour: 0, interval: '15' }, time: '0:15', count: 5 }, { _id: { hour: 0, interval: '30' }, time: '0:30', count: 1 }, { _id: { hour: 0, interval: '45' }, time: '0:45', count: 2 }, { _id: { hour: 1, interval: '0' }, time: '1:0', count: 4 }, { _id: { hour: 1, interval: '15' }, time: '1:15', count: 3 }, { _id: { hour: 1, interval: '30' }, time: '1:30', count: 5 }, { _id: { hour: 1, interval: '45' }, time: '1:45', count: 1 }]

var group = a.reduce((r, a) => {
  console.log("a", a);
  console.log('r', r);
  r[a._id.hour] = [...r[a._id.hour] || [], a];
  return r;
}, {});
console.log("group", group);

1
  • Please explain what do you expect Commented Jan 13, 2020 at 9:06

3 Answers 3

2

Check if the object with that hour exists in the accumulator object first - if it doesn't, create one, then assign count to that object's [interval] property, and get the Object.values at the end to turn it back into an array:

const input=[{_id:{hour:0,interval:"0"},time:"0:0",count:10},{_id:{hour:0,interval:"15"},time:"0:15",count:5},{_id:{hour:0,interval:"30"},time:"0:30",count:1},{_id:{hour:0,interval:"45"},time:"0:45",count:2},{_id:{hour:1,interval:"0"},time:"1:0",count:4},{_id:{hour:1,interval:"15"},time:"1:15",count:3},{_id:{hour:1,interval:"30"},time:"1:30",count:5},{_id:{hour:1,interval:"45"},time:"1:45",count:1}];

const groupedObj = {};
for (const { _id: { hour, interval }, count } of input) {
  if (!groupedObj[hour]) {
    groupedObj[hour] = { time: hour };
  }
  groupedObj[hour][interval] = count;
}
const output = Object.values(groupedObj);
console.log(output);

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you..Its really helps
1

Reduce the array, and create an object for each _id.time. Assign the current [interval] = count to the object. Get the entries, and use Array.from() to convert the entries to an array of the required form:

const arr = [{"_id":{"hour":0,"interval":"0"},"time":"0:0","count":10},{"_id":{"hour":0,"interval":"15"},"time":"0:15","count":5},{"_id":{"hour":0,"interval":"30"},"time":"0:30","count":1},{"_id":{"hour":0,"interval":"45"},"time":"0:45","count":2},{"_id":{"hour":1,"interval":"0"},"time":"1:0","count":4},{"_id":{"hour":1,"interval":"15"},"time":"1:15","count":3},{"_id":{"hour":1,"interval":"30"},"time":"1:30","count":5},{"_id":{"hour":1,"interval":"45"},"time":"1:45","count":1}];

// convert the entries to an array
const result = Array.from(Object.entries(
    arr.reduce((r, o) => {
      const { hour, interval } = o._id; // get the hour and interval
      
      if(!r[hour]) r[hour] =  {}; // create a the hour object
     
      r[hour][interval] = o.count; // add the interval and count
      
      return r;
    }, {})
  ), ([time, values]) => ({ time, ...values })); // generate the result objects

console.log(result)

Comments

1

You can group object by reduce method. So at first you need to group by hour and then just add interval properties from each iteration of reduce method to the hour property:

const result = arr.reduce((a, c) => {
   a[c._id.hour] = a[c._id.hour] || {};
   a[c._id.hour].time = c._id.hour;
   a[c._id.hour][c._id.interval] = c.count;    
   return a;
 }, {})

 console.log(result);

An example:

let arr = [
  {
    _id: {
      hour: 0,
      interval: '0'
    },
    time: '0:0',
    count: 10
  },
  {
    _id: {
      hour: 0,
      interval: '15'
    },
    time: '0:15',
    count: 5
  },
  {
    _id: {
      hour: 0,
      interval: '30'
    },
    time: '0:30',
    count: 1
  },
  {
    _id: {
      hour: 0,
      interval: '45'
    },
    time: '0:45',
    count: 2
  },
  {
    _id: {
      hour: 1,
      interval: '0'
    },
    time: '1:0',
    count: 4
  },
  {
    _id: {
      hour: 1,
      interval: '15'
    },
    time: '1:15',
    count: 3
  },
  {
    _id: {
      hour: 1,
      interval: '30'
    },
    time: '1:30',
    count: 5
  },
  {
    _id: {
      hour: 1,
      interval: '45'
    },
    time: '1:45',
    count: 1
  }
]


 const result = arr.reduce((a, c) => {
   a[c._id.hour] = a[c._id.hour] || {};
   a[c._id.hour].time = c._id.hour;
   a[c._id.hour][c._id.interval] = c.count;

   return a;
 }, {})

 console.log(result);

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.