0

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}`};
  });
});
3
  • 1
    what's wrong with what the OP wants @anttud? (hint: is IS valid) Commented Aug 9, 2018 at 10:59
  • @JaromandaX is correct Commented Aug 9, 2018 at 11:00
  • considering you've produced the required result @AnkitAgarwal it wasn't hard to be correct :p Commented Aug 9, 2018 at 11:01

5 Answers 5

2

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

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

4 Comments

there's a little redundancy and repetition in your code ... 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; }, []);
@JaromandaX thanks. Appreciate that. Updated with your suggested code
Thanks for posting :)
@molinto glad to help you :)
1
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]}})

1 Comment

Thanks for posting :)
0

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

5 Comments

lots of undefined in your output
Thanks @titus, getting lots of 'undefined' when running though
@JaromandaX Yes, I've just notice that, is probably because I'm pushing references instead of new objects.
@molinto fixed it.
Thanks for posting :)
0

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

Comments

0

Here's a ramda example too for reference:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.