'How to transform a dataset and aggregate values with javascript/typescript
I want to take a dataset which is an object where the the value field has an array value. I want to iterate through the array and group them by the different ids. I also want it to get an aggregate of "count"(total count) and have a field for the different type of "status" and its associated count.
"value": [
{
"count": 5,
"id": "id1",
"status": 1
},
{
"count": 2,
"id": "id1",
"status": 3
},
{
"count": 2,
"id": "id1",
"status": 4
},
{
"count": 1,
"id": "id2",
"status": 0
},
{
"count": 2,
"id": "id2",
"status": 1
},
{
"count": 7,
"id": "id2",
"status": 2
},
{
"count": 5,
"id": "id2",
"status": 3
},
{
"count": 3,
"id": "id2",
"status": 4
}
]
}```
desired output is a map where the keys are ids and value is made up of totalCount(aggregate of all the counts of that id), statusx(where x is the different type of status. There will be a limited type of status. Maybe 5 or so) that has the count of that status, and "status" to show what type of status it is(0-5):
{
id1 : { totalCount: 9, status1 : 5, status3: 2, status4:2},
id2 : { totalCount: 18, status0 : 1, status1 : 2, status2: 7, status3: 5, status4:3}
}
Solution 1:[1]
Super specific and weird ask, but here ya go. You can do this easily with the reduce
method:
const object = {
value: [
{
count: 5,
id: 'id1',
status: 1,
},
{
count: 2,
id: 'id1',
status: 3,
},
{
count: 2,
id: 'id1',
status: 4,
},
{
count: 1,
id: 'id2',
status: 0,
},
{
count: 2,
id: 'id2',
status: 1,
},
{
count: 7,
id: 'id2',
status: 2,
},
{
count: 5,
id: 'id2',
status: 3,
},
{
count: 3,
id: 'id2',
status: 4,
},
],
};
interface Output {
[key: string]: {
totalCount: number;
[key: string]: number;
};
}
const group = ({ value }: typeof object) => {
return value.reduce((acc: Output, { count, id, status }) => {
if (!acc[id]) acc[id] = { totalCount: count };
else acc[id].totalCount += count;
if (!acc[id][`status${status}`]) acc[id][`status${status}`] = 1
else acc[id][`status${status}`] += 1
return acc;
}, {} as Output);
};
console.dir(group(object));
Compiled:
"use strict";
const object = {
value: [
{
count: 5,
id: 'id1',
status: 1,
},
{
count: 2,
id: 'id1',
status: 3,
},
{
count: 2,
id: 'id1',
status: 4,
},
{
count: 1,
id: 'id2',
status: 0,
},
{
count: 2,
id: 'id2',
status: 1,
},
{
count: 7,
id: 'id2',
status: 2,
},
{
count: 5,
id: 'id2',
status: 3,
},
{
count: 3,
id: 'id2',
status: 4,
},
],
};
const group = ({ value }) => {
return value.reduce((acc, { count, id, status }) => {
if (!acc[id])
acc[id] = { totalCount: count };
else
acc[id].totalCount += count;
if (!acc[id][`status${status}`])
acc[id][`status${status}`] = 1;
else
acc[id][`status${status}`] += 1;
return acc;
}, {});
};
console.dir(group(object));
Solution 2:[2]
This is written in TypeScript. You can refer to: https://www.typescriptlang.org/docs/handbook/2/indexed-access-types.html if you want to learn more about the 'index access types'
Edit: https://stackblitz.com/edit/typescript-cbfodv, working stackblitz code is available here.
const dataArray = [
{
count: 5,
id: 'id1',
status: 1,
},
{
count: 2,
id: 'id1',
status: 3,
},
{
count: 2,
id: 'id1',
status: 4,
},
{
count: 1,
id: 'id2',
status: 0,
},
{
count: 2,
id: 'id2',
status: 1,
},
{
count: 7,
id: 'id2',
status: 2,
},
{
count: 5,
id: 'id2',
status: 3,
},
{
count: 3,
id: 'id2',
status: 4,
},
];
var obj: { [k: string]: any } = {};
dataArray.forEach((elem) => {
let foundGroup = obj[elem.id];
let statusPropertyName = 'status' + elem.status;
if (foundGroup === undefined) {
obj[elem.id] = {
totalCount: elem.count,
[statusPropertyName]: elem.count,
};
} else {
foundGroup['totalCount'] += elem.count;
let foundStatus = foundGroup[statusPropertyName];
if (foundStatus === undefined) {
foundGroup[statusPropertyName] = elem.count;
} else {
foundStatus += elem.count;
}
}
});
console.log(obj);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | mstephen19 |
Solution 2 |