I have the following array of dicts
var response = [{
"ShoppingCart": "cart1",
"Class": "Gen",
"Type": "300",
"SubClass": "Mens",
"Points": 0.9
},
{
"ShoppingCart": "cart2",
"Class": "Lux",
"Type": "3002C",
"SubClass": "Mens",
"Points": 0.75
},
{
"ShoppingCart": "cart3",
"Class": "Lux",
"Type": "380",
"SubClass": "Ladies",
"Points": 0.5
},
{
"ShoppingCart": "cart4",
"Class": "Lux",
"Type": "300",
"SubClass": "Cabin",
"Points": 1
},
{
"ShoppingCart": "cart5",
"Class": "Comfort",
"Type": "380",
"SubClass": "Ladies",
"Points": 1
},
{
"ShoppingCart": "cart6",
"Class": "Gen",
"Type": "380",
"SubClass": "Cabin",
"Points": 0.9
},
{
"ShoppingCart": "cart7",
"Class": "Gen",
"Type": "300",
"SubClass": "Cabin",
"Points": 0.7
},
{
"ShoppingCart": "cart8",
"Class": "Gen",
"Type": "380PC",
"SubClass": "Ladies",
"Points": 0.7
},
{
"ShoppingCart": "cart9",
"Class": "Lux",
"Type": "380",
"SubClass": "Cabin",
"Points": 0.5
},
{
"ShoppingCart": "cart10",
"Class": "Lux",
"Type": "380",
"SubClass": "Ladies",
"Points": 0.5
}
]
I am using reduce function and When i do a groupby and sum the Points , the Class is repeated and not unique , How can i perform a groupby and sum the unique values .
I know lodash’s groupby function solves, how can i do it with the reduce function itself ?
The last Class comfort is not coming in the output , why is that ?
the code so far
result = [];
response.reduce(function(res, value) {
if (!res[value.Type]) {
res[value.Type] = { Type: value.Type, Class: value.Class, Points: 0 };
result.push(res[value.Type])
}
res[value.Type].Points += parseFloat(value.Points);
return res;
}, {});
console.log(result);
result:
[
{ Type: '300', Class: 'Gen', Points: 2.5999999999999996 },
{ Type: '3002C', Class: 'Lux', Points: 0.75 },
{ Type: '380', Class: 'Lux', Points: 3.4 },
{ Type: '380PC', Class: 'Gen', Points: 0.7 }
]
expected result:
[
{ Type: '300', Class: 'Gen', Points: 2.5999999999999996 },
{ Type: '3002C', Class: 'Lux', Points: 0.75 },
{ Type: '380', Class: 'Lux', Points: 3.4 },
{ Type: '380PC', Class: 'Gen', Points: 0.7 },
{ Type: '380', Class: 'Comfort', Points: 1 }
]
What am i missing in this reduce function ?
Modified Code as per epascarello’s suggestions
response.reduce(function(res, value) {
const key = value.Type + "-" + value.Class;
if (!res[key]) {
res[key] = { Type: value.Type, Class: value.Class, Points: 0 };
result.push(res[key])
}
res[key].Points += parseFloat(value.Points);
return res;
}, {});
console.log(result);
>Solution :
I think this is more what you’re looking for.
Basically, for each item in response it will try to find an item in the results array that has the same Type and Class as the provided item. If it finds one it will increment that item’s Points by the provided Points, if not it will append a new item onto the results array.
.reduce is a very useful function, but how you had it before was not utilizing its capabilities.
var response = [{
"ShoppingCart": "cart1",
"Class": "Gen",
"Type": "300",
"SubClass": "Mens",
"Points": 0.9
},
{
"ShoppingCart": "cart2",
"Class": "Lux",
"Type": "3002C",
"SubClass": "Mens",
"Points": 0.75
},
{
"ShoppingCart": "cart3",
"Class": "Lux",
"Type": "380",
"SubClass": "Ladies",
"Points": 0.5
},
{
"ShoppingCart": "cart4",
"Class": "Lux",
"Type": "300",
"SubClass": "Cabin",
"Points": 1
},
{
"ShoppingCart": "cart5",
"Class": "Comfort",
"Type": "380",
"SubClass": "Ladies",
"Points": 1
},
{
"ShoppingCart": "cart6",
"Class": "Gen",
"Type": "380",
"SubClass": "Cabin",
"Points": 0.9
},
{
"ShoppingCart": "cart7",
"Class": "Gen",
"Type": "300",
"SubClass": "Cabin",
"Points": 0.7
},
{
"ShoppingCart": "cart8",
"Class": "Gen",
"Type": "380PC",
"SubClass": "Ladies",
"Points": 0.7
},
{
"ShoppingCart": "cart9",
"Class": "Lux",
"Type": "380",
"SubClass": "Cabin",
"Points": 0.5
},
{
"ShoppingCart": "cart10",
"Class": "Lux",
"Type": "380",
"SubClass": "Ladies",
"Points": 0.5
}
];
var grouped = response.reduce((res, value) => {
const ext = res.find(({
Type,
Class
}) => {
return Type === value.Type && Class === value.Class;
});
if (ext) {
ext.Points += value.Points;
} else {
res.push({
Type: value.Type,
Class: value.Class,
Points: value.Points
});
}
return res;
}, []);
console.log(grouped);