I have a data structure like this one. It's basiccally an array of objects.
const dataset = [
{
a: { total: 2, name: "red" },
b: { total: 3, name: "gold" },
c: { total: 6, name: "rose" },
},
{
a: { total: 10, name: "red" },
b: { total: 7, name: "purple" },
},
{
a: { total: 1, name: "pink" },
b: { total: 14, name: "blue" },
c: { total: 10, name: "rose" },
},
{
b: { total: 2, name: "green" },
c: { total: 18, name: "rose" },
},
]
This is what I would like to compute as result:
const result = {
a: 13,
b: 26,
c: 34,
}
So, I need a sum of values total
by objects with same key.I try to explain myself using the previous example:
const result = {
a: 13, // 2 10 1
b: 26, // 3 7 14 2
c: 34, // 6 10 18
}
Note that the keys a
, b
, c
can be a lot (not only 3) and I don't know their name because they are dynamic.
How can I do that? I thought to group the objects {total, name}
by keys and then sum by total
but how? Is there a Lodash function that can help me?
CodePudding user response:
It's pretty simple, iterate over the dataset, then iterate over all keys in the dataset's row:
const dataset = [
{ a: { total: 2, name: "red" }, b: { total: 3, name: "gold" }, c: { total: 6, name: "rose" } },
{ a: { total: 10, name: "red" }, b: { total: 7, name: "purple" } },
{ a: { total: 1, name: "pink" }, b: { total: 14, name: "blue" }, c: { total: 10, name: "rose" } },
{ b: { total: 2, name: "green" }, c: { total: 18, name: "rose" } },
];
const result = {};
dataset.forEach(row => {
for (let key in row) {
if (!result[key])
result[key] = 0;
result[key] = row[key].total;
}
});
console.log(result);
CodePudding user response:
Why not use reduce
with for of
:
const dataset = [{a: { total: 2, name: "red" }, b: { total: 3, name: "gold" }, c: { total: 6, name: "rose" }, }, {a: { total: 10, name: "red" }, b: { total: 7, name: "purple" }, }, {a: { total: 1, name: "pink" }, b: { total: 14, name: "blue" }, c: { total: 10, name: "rose" }, }, {b: { total: 2, name: "green" }, c: { total: 18, name: "rose" }, }, ];
const result = dataset.reduce((res, cur) => {
for (const [key, value] of Object.entries(cur)) {
res[key] = (res[key] || 0) value.total;
}
return res;
}, {});
console.log(result);
CodePudding user response:
You can use array reduce :
const dataset = [
{
a: { total: 2, name: "red" },
b: { total: 3, name: "gold" },
c: { total: 6, name: "rose" }
},
{
a: { total: 10, name: "red" },
b: { total: 7, name: "purple" }
},
{
a: { total: 1, name: "pink" },
b: { total: 14, name: "blue" },
c: { total: 10, name: "rose" }
},
{
b: { total: 2, name: "green" },
c: { total: 18, name: "rose" }
}
];
function getCount() {
return dataset.reduce((countObj, nextVal) => {
Object.keys(nextVal).forEach(key => {
if(countObj[key]){
countObj[key] = nextVal[key].total;
}else{
countObj[key] = nextVal[key].total;
}
});
return countObj;
}, {});
}
console.log(getCount());
CodePudding user response:
Idea
Build a dictionary of totals, adding entries as you encounter properties for the first time.
Implementation
Iterate over items in your dataset, for each item iterate over the object properties.
Assumption: Each item object has a property total
holding a number.
function tally ( pa_dataset ) {
let dict_totals = {}
;
pa_dataset.forEach ( po_record => {
Object.entries(po_record).forEach ( pa_entry => {
let s_key = pa_entry[0]
, x_value = pa_entry[1]
;
if (!dict_totals.hasOwnProperty(s_key)) { dict_totals[s_key] = 0; }
dict_totals[s_key] = x_value.total;
});
});
return dict_totals;
} // tally
// Test
const dataset = [
{
a: { total: 2, name: "red" },
b: { total: 3, name: "gold" },
c: { total: 6, name: "rose" },
},
{
a: { total: 10, name: "red" },
b: { total: 7, name: "purple" },
},
{
a: { total: 1, name: "pink" },
b: { total: 14, name: "blue" },
c: { total: 10, name: "rose" },
},
{
b: { total: 2, name: "green" },
c: { total: 18, name: "rose" },
},
];
console.log ( 'Totals:' );
console.log ( tally(dataset));
Remarks
There is no lodash function specifically implementing the desired functionality.
CodePudding user response:
const map = new Map()
dataset.forEach(obj=>{
Object.keys(obj).forEach(key=>{
const value = obj[key]
if(value?.total){
if(!map.has(key)){
map.set(key,0)
}
map.set(key,map.get(key) value.total)
}
})
})
map.forEach((v,k)=>{
console.log(`${k}:${v}`)
})