Restructure JavaScript object into array of objects with named keys

I have the following JavaScript object:

const groupedData = {
  "1":[
    {"x":"2021-02-05","y":1},
    {"x":"2021-02-05","y":1},
    {"x":"2021-02-06","y":1}
  ],
  "2":[
    {"x":"2021-02-05","y":1},
    {"x":"2021-02-06","y":1},
    {"x":"2021-02-07","y":1},
    {"x":"2021-02-07","y":1},
    {"x":"2021-02-07","y":1},
    {"x":"2021-02-08","y":1}
  ]
}

I’d like to group the objects in each of the arrays by x and sum by y and shape the data into a slightly different structure so it can be consumed by a charting library. I have the following function which does the grouping and summing successfully:

const formattedData = [];
Object.keys(groupedData).map((key) => {
  var totals = groupedData[key].reduce(function (r, o) {
    (r[o.x]) ? r[o.x] += o.y : r[o.x] = o.y;
    return r;
  }, {});
  formattedData.push({ 'name': key, 'data': totals })
});

This outputs the following:

[
  {
    "name":"1",
    "data": {
      "2021-02-05":2,
      "2021-02-06":1 
    }
  },
  {
    "name":"2",
    "data": {
      "2021-02-05":1,
      "2021-02-06":1,
      "2021-02-07":3,
      "2021-02-08":1
    }
  }
]

However, I’d like the data to be in the following format:

[
  {
    "name":"1",
    "data":[
      {"x":"2021-02-05","y":2},
      {"x":"2021-02-06","y":1}
    ]
  },
  {
    "name":"2",
    "data":[
      {"x":"2021-02-05","y":1},
      {"x":"2021-02-06","y":1},
      {"x":"2021-02-07","y":3},
      {"x":"2021-02-08","y":1}
    ]
  }
]

I’m struggling to come up with a neat way to do this final part of the formatting. Could anyone advise how to modify the formatting function to implement this last step, in a neat way?

Many thanks

Answer

You could map the entries of the object and group the values.

const
    data = { 1: [{ x: "2021-02-05", y: 1 }, { x: "2021-02-05", y: 1 }, { x: "2021-02-06", y: 1 }], 2: [{ x: "2021-02-05", y: 1 }, { x: "2021-02-06", y: 1 }, { x: "2021-02-07", y: 1 }, { x: "2021-02-07", y: 1 }, { x: "2021-02-07", y: 1 }, { x: "2021-02-08", y: 1 }] },
    result = Object.entries(data).map(([name, data]) => ({
        name,
        data: Object.values(data.reduce((r, { x, y }) => {
            r[x] ??= { x, y: 0 };
            r[x].y += y;
            return r;
        }, {}))
    }));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Leave a Reply

Your email address will not be published. Required fields are marked *