molinto
molinto

Reputation: 3

Flatten an array object to single object - Javascript

I'm using ChartKick to represent some data in the graphs in Multiple series line chart. The required format is:

let data = [
   { name: 'sharry', data: { '2008-08-02': 10006097, '2018-08-03': 10670, etc }},
   { name: 'stuart', data: { '2018-08-01' :1401231321, '2018-08-04': 2500000000, etc }}
];

The data I get from the database is:

let user_usage = [
  { "name":"stuart", "data": { "2018-08-02":10006097 } },
  { "name":"stuart", "data": { "2018-08-03":10670 } },
  { "name":"stuart", "data": { "2018-08-05":5800000 } },
  { "name":"stuart", "data": { "2018-08-07":10789000 } },
  { "name":"stuart", "data": { "2018-08-08":1033000000 } },
  { "name":"sharry", "data": { "2018-08-01":1401231321 } },
  { "name":"sharry", "data": { "2018-08-04":2500000000 } }
];

I've been trying for 2 days to get the database response into the required format above Any help greatly appreciated guys. Here is what I have so far. I'm using Ramda but ES6 is fine to use:

let chartdata = [];
let u = R.groupBy(R.prop('name'))(user_usage);

Object.keys(u).forEach((name, index) => {
  chartdata.push({ name , data: {} });
  let usage = u[name];

  Object.keys(usage).forEach(row => {
    let data = usage[row].data;
    let date = Object.keys(data)[0];
    let total = data[Object.keys(data)[0]];
    chartdata[index].data = Object.assign({}, {`${date}: ${total}`};
  });
});

Upvotes: 0

Views: 70

Answers (5)

Ross Mackay
Ross Mackay

Reputation: 972

Here's a ramda example too for reference:

pipe(
  groupBy(prop('name')),
  map(pipe(pluck('data'), mergeAll)),
)

Upvotes: 0

amrender singh
amrender singh

Reputation: 8239

You can use Object.assign() and Map() for a more efficient solution:

let user_usage = [ { "name":"stuart", "data": { "2018-08-02":10006097 } }, { "name":"stuart", "data": { "2018-08-03":10670 } }, { "name":"stuart", "data": { "2018-08-05":5800000 } }, { "name":"stuart", "data": { "2018-08-07":10789000 } }, { "name":"stuart", "data": { "2018-08-08":1033000000 } }, { "name":"sharry", "data": { "2018-08-01":1401231321 } }, { "name":"sharry", "data": { "2018-08-04":2500000000 } } ];
var map = new Map();
user_usage.forEach((obj)=>{
  if(map.has(obj.name)){
    var mapObject = map.get(obj.name);
    Object.assign(mapObject.data, obj.data);
    map.set(obj.name ,mapObject); 
  } else{
    map.set(obj.name, Object.assign({},obj));
  }
});
let result = Array.from(map.values());

console.log(result);

Upvotes: 0

Ankit Agarwal
Ankit Agarwal

Reputation: 30739

Use Array.reduce() with Object.assign() so that you can assign the data object to the existing item of the accumulator.

let user_usage = [
  { "name":"stuart", "data": { "2018-08-02":10006097 } },
  { "name":"stuart", "data": { "2018-08-03":10670 } },
  { "name":"stuart", "data": { "2018-08-05":5800000 } },
  { "name":"stuart", "data": { "2018-08-07":10789000 } },
  { "name":"stuart", "data": { "2018-08-08":1033000000 } },
  { "name":"sharry", "data": { "2018-08-01":1401231321 } },
  { "name":"sharry", "data": { "2018-08-04":2500000000 } }
];
var res = user_usage.reduce((acc, item) => {
  var existItem = acc.find(({name}) => name === item.name);
  if(existItem){
    Object.assign(existItem.data,item.data);
  } else {
    acc.push(item);
  }
  return acc;
}, 
[]);
console.log(res);

Upvotes: 2

Titus
Titus

Reputation: 22474

You can do something like this:

let user_usage = [
  { "name":"stuart", "data": { "2018-08-02":10006097 } },
  { "name":"stuart", "data": { "2018-08-03":10670 } },
  { "name":"stuart", "data": { "2018-08-05":5800000 } },
  { "name":"stuart", "data": { "2018-08-07":10789000 } },
  { "name":"stuart", "data": { "2018-08-08":1033000000 } },
  { "name":"sharry", "data": { "2018-08-01":1401231321 } },
  { "name":"sharry", "data": { "2018-08-04":2500000000 } }
];

let data = user_usage.reduce((a, c) => {
  let key = Object.keys(c.data)[0];
  let found = a.find(v => v.name === c.name);
  if(found){
    found.data[key] = c.data[key];
  }else{
    a.push(c);
  }
  return a;
}, [])

console.log(data);

Upvotes: 0

Daphoque
Daphoque

Reputation: 4678

var obj = {};
user_usage.forEach(function(e){
    if(!obj[e.name]){
       obj[e.name] = e.data;
    } else {
       obj[e.name] = Object.assign(obj[e.name], e.data)
    }
});
var array = Object.keys(obj).map(function(e){return {name: e, data: obj[e]}})

Upvotes: 1

Related Questions