Reputation: 53
This is the original array:
[
{
id: robin,
savings: 5500,
cost: 1200
},
{
id: robin_1,
savings: 50,
cost: 100
},
{
id: robin_2,
savings: 50,
cost: 150
},
{
id: steve,
savings: 100,
cost: 1000
},
{
id: steve_1,
savings: 50,
cost: 550
},
{
id: steve_2,
savings: 50,
cost: 150
},
]
I'm trying to get this below expected output .
{
robin :{
allTime:{
savings: 5500,
cost: 1200,
},
today:{
savings: 100,
cost: 250
}
},
steve:{
allTime: {
savings:100,
cost: 1000
},
today: {
savings: 100,
cost: 700
}
}
}
Basically when id is only robin set the output in allTime key and when there are some suffixes after robin like 1,2,3 then sum them and set it into today.
Have tried by normally looping them and groupby with _.sumBy() like below attempt but have failed.
var output = _.groupBy(resultSet, value => value.id)
.map((objs, key) => (
{ 'id': key,
'savings': _.sumBy(objs,'savings'),
'cost': _.sumBy(objs, 'cost'))
}
.value();
Upvotes: 0
Views: 59
Reputation: 2679
I think I'd go with Array.prototype.reduce()
like this:
const input = [
{ id: 'robin', savings: 5500, cost: 1200 },
{ id: 'robin_1', savings: 50, cost: 100 },
{ id: 'robin_2', savings: 50, cost: 150 },
{ id: 'steve', savings: 100, cost: 1000 },
{ id: 'steve_1', savings: 50, cost: 550 },
{ id: 'steve_2', savings: 50, cost: 150 },
{ id: 'bob', savings: 1000, cost: 300 },
{ id: 'mark_1', savings: 50, cost: 150 }
];
const output = input.reduce((outObj, item) => {
const { savings, cost } = item;
const [mainKey, suffix] = item.id.split('_');
const subKey = suffix === undefined ? 'allTime' : 'today';
if (!outObj.hasOwnProperty(mainKey)) {
outObj[mainKey] = {
[subKey]: { savings, cost }
}
} else {
if (!outObj[mainKey].hasOwnProperty(subKey)) {
outObj[mainKey][subKey] = { savings, cost }
} else {
outObj[mainKey][subKey].savings += savings;
outObj[mainKey][subKey].cost += cost;
}
}
return outObj;
}, {})
//test
console.log(output);
With this approach you do not "hard-code" the properties allTime
and today
into each entry of the output object; instead you dynamically add them only if/where they are needed (see the examples with bob
and mark
where only allTime
or today
is added)
Upvotes: 0
Reputation: 4419
I managed to do it like this using array#reduce
:
let data = [
{ id: 'robin', savings: 5500, cost: 1200 },
{ id: 'robin_1', savings: 50, cost: 100 },
{ id: 'robin_2', savings: 50, cost: 150 },
{ id: 'steve', savings: 100, cost: 1000 },
{ id: 'steve_1', savings: 50, cost: 550 },
{ id: 'steve_2', savings: 50, cost: 150 },
];
let newData = data.reduce((acc, { id, savings, cost }) => {
let [pre, suff] = id.split('_');
if (!acc[pre]) acc[pre] = { allTime: {}, today: { savings: 0, cost: 0 } };
if (!suff) acc[pre].allTime = { savings, cost };
else (acc[pre].today.savings += savings), (acc[pre].today.cost += cost);
return acc;
}, {});
console.log(newData);
And like this using a for...of
loop:
let data = [
{ id: 'robin', savings: 5500, cost: 1200 },
{ id: 'robin_1', savings: 50, cost: 100 },
{ id: 'robin_2', savings: 50, cost: 150 },
{ id: 'steve', savings: 100, cost: 1000 },
{ id: 'steve_1', savings: 50, cost: 550 },
{ id: 'steve_2', savings: 50, cost: 150 },
];
let newData = {};
for ({ id, savings, cost } of data) {
let [pre, suff] = id.split('_');
if (!newData[pre]) newData[pre] = { allTime: {}, today: { savings: 0, cost: 0 } };
if (!suff) newData[pre].allTime = { savings, cost };
else (newData[pre].today.savings += savings), (newData[pre].today.cost += cost);
}
console.log(newData)
Upvotes: 2
Reputation: 527
Try this looped by reduce
const data = [
{
id: "robin",
savings: 5500,
cost: 1200
},
{
id: "robin_1",
savings: 50,
cost: 100
},
{
id: "robin_2",
savings: 50,
cost: 150
},
{
id: "steve",
savings: 100,
cost: 1000
},
{
id: "steve_1",
savings: 50,
cost: 550
},
{
id: "steve_2",
savings: 50,
cost: 150
},
];
const res = data.reduce((acc, val) => {
const splitVal = val.id.split("_")[0];
if(acc[val.id] || acc[splitVal]){
acc[splitVal].today.savings+=val.savings;
acc[splitVal].today.cost+=val.cost;
}else{
acc[val.id] = {
allTime:{
savings: val.savings,
cost: val.cost,
},
today:{
savings: 0,
cost: 0
}
}
}
return acc;
}, {});
console.log(res);
Upvotes: 0