2

I am working with highChart to create a column chart. Any how I reached to creating following arrayofObj via communicating with database.

Now, I require to transform following source array of object to below output.

var source = [
{data: 258, name: '2014'}
{data: 18, name: '2016'}
{data: 516, name: '2014'}
{data: 0, name: '2014'}
{data: 354, name: '2014'}
{data: 18, name: '2016'}
]`

Convert this array of object to

Output

[{
    name: '2014',
    data: [258, 516, 354]
  }, {
    name: '2016',
    data: [18, 0, 18]
}]

Basically, I want my array to group by name (year) and data should be in array

Here is the solutions which i have applied.

var source = [];
_.each(source, function(singlerec) {
      source.push({
        name: singlerec.name,
        data: singlerec.data  // Here It only assign single record
      });
    });
Denish
  • 2,800
  • 2
  • 23
  • 33
  • @T.J.Crowder Thanks, Of course I have tried first, But you are right, I have added my progress in question. – Denish Jul 20 '16 at 16:11
  • Add what's *wrong* with the output of your solution. Also, with respect, your solution looks like it doesn't make any attempt *at all* to group things by `name`. Which is very much like asking someone else to add the grouping-by-name for you. – T.J. Crowder Jul 20 '16 at 16:12
  • Also, search is your friend. :-) http://stackoverflow.com/questions/36069213/javascript-group-data-in-objects, http://stackoverflow.com/questions/14592799/object-array-group-by-an-element, http://stackoverflow.com/questions/38079037/group-items-in-javascript-array-object – T.J. Crowder Jul 20 '16 at 16:13
  • Possible duplicate of [Lodash create collection from duplicate object keys](http://stackoverflow.com/questions/38438645/lodash-create-collection-from-duplicate-object-keys) – 4castle Jul 20 '16 at 16:21
  • @T.J.Crowder Lodash is so succinct, that the solution is usually all or nothing. I don't feel that seeing the OP's attempt improves the question, just as long as they actually made a real attempt. Functional programming can be difficult to grasp, especially when people try to blend it with imperative programming. – 4castle Jul 20 '16 at 17:33

3 Answers3

5

In Lodash, I always use _.groupBy and then _.map to the output format.

var source = [{"data":258,"name":"2014"},{"data":18,"name":"2016"},{"data":516,"name":"2014"},{"data":0,"name":"2014"},{"data":354,"name":"2014"},{"data":18,"name":"2016"}];

var output = _(source)
  .groupBy('name')
  .map(function(v, k) { return { name: k, data: _.map(v, 'data') } })
  .value();

console.log(output);
<script src="https://cdn.jsdelivr.net/lodash/4.13.1/lodash.min.js"></script>
4castle
  • 32,613
  • 11
  • 69
  • 106
2

I use a pure javascript function:

const pick = (obj, paths) => ({...paths.reduce((a, k) => ({...a, [k]: obj[k]}), {})})

function groupByAndConcat(data, groupBy, sums) {
    return data.reduce((results, r) => {
        const e = results.find((x) => groupBy.every((g) => x[g] === r[g]));
        if (e) {
            sums.forEach((k) => e[k] = [].concat(e[k], r[k]));
        } else {
            results.push(pick(r, groupBy.concat(sums)));
        }
        return results;
    }, []);
}

So given your sample source:

const source = [
    {data: 258, name: '2014'},
    {data: 18, name: '2016'},
    {data: 516, name: '2014'},
    {data: 0, name: '2014'},
    {data: 354, name: '2014'},
    {data: 18, name: '2016'},
];

console.log(groupByAndConcat(source, ["name"], ["data"]))

outputs:

[{ name: "2014", data: Array [258, 516, 0, 354] }, { name: "2016", data: Array [18, 18] }]

It is also possible to group by or do operations on several props:

groupByAndConcat(source, ["name","month"], ["data","data2"])
1

there's a way to iterate array once with reduce and even without lodash.

source.reduce((p, n) => {
    (p[n.name] || (p[n.name] = [])).push(n.data);
    return p
}, {})
evilive
  • 1,781
  • 14
  • 20