I have the following structure:
groupedData = {
rice: [
{
name: 'white rice'
quantity: 2
category: 'rice'
},
{
name: 'brown rice'
quantity: 1
category: 'rice'
}
],
water: [
{
name: 'sparkle water'
quantity: 1
category: 'water'
},
{
name: 'still water'
quantity: 1
category: 'water'
}
],
tea: [{
name: 'green tea'
quantity: 1
category: 'water'
}],
}
What I want to achieve is to have a summed quantity of each category, so as: rice: 3, water: 2, tea: 1
I tried the following:
const sum = () => {
let quantity = []
for (var property in groupedData) {
for (let i=0; i< groupedData[property].length; i ){
quantity[property] = groupedData[property][i].quantity;
}
}
return quantity;
}
but it doesn't return summed data but only the quantity of the first item
[rice: 2, water: 1, tea: 1]
CodePudding user response:
This is based on your question.
const groupedData = {
rice: [{
name: 'white rice',
quantity: 2,
category: 'rice',
},
{
name: 'brown rice',
quantity: 1,
category: 'rice',
}
],
water: [{
name: 'sparkle water',
quantity: 1,
category: 'water',
},
{
name: 'still water',
quantity: 1,
category: 'water',
}
],
tea: [{
name: 'green tea',
quantity: 1,
category: 'water',
}],
}
const sum = () => {
let quantity = {}
for (var property in groupedData) {
for (let i = 0; i < groupedData[property].length; i ) {
quantity = {
...quantity,
[property]: quantity[property] ? quantity[property] groupedData[property][i].quantity : groupedData[property][i].quantity
}
}
}
return quantity;
}
console.log(sum());
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
And this is my answer with reduce
const groupedData = {
rice: [{
name: 'white rice',
quantity: 2,
category: 'rice',
},
{
name: 'brown rice',
quantity: 1,
category: 'rice',
}
],
water: [{
name: 'sparkle water',
quantity: 1,
category: 'water',
},
{
name: 'still water',
quantity: 1,
category: 'water',
}
],
tea: [{
name: 'green tea',
quantity: 1,
category: 'water',
}],
}
const sum = () => {
let res = {}
for (var props in groupedData) {
const item = groupedData[props].reduce((acc, cur) => {
acc = cur.quantity;
return acc;
}, 0);
res[props] = item;
}
return res;
}
console.log(sum());
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
You can do something like this:
const result = Object.entries(groupedData).reduce((prev, [k, v]) => {
const sums = {
...prev,
[k]: v.reduce((p, c) => p c.quantity, 0),
}
return sums
}, {})
Here is the full snippet:
const groupedData = {
rice: [{
name: 'white rice',
quantity: 2,
category: 'rice',
},
{
name: 'brown rice',
quantity: 1,
category: 'rice',
},
],
water: [{
name: 'sparkle water',
quantity: 1,
category: 'water',
},
{
name: 'still water',
quantity: 1,
category: 'water',
},
],
tea: [{
name: 'green tea',
quantity: 1,
category: 'water',
}, ],
}
const result = Object.entries(groupedData).reduce((prev, [k, v]) => {
const sums = {
...prev,
[k]: v.reduce((p, c) => p c.quantity, 0),
}
return sums
}, {})
console.log(result)
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
Your solution does not add the nodes. Just add the quantity
of each node
const groupedData = {
rice: [
{ name: 'white rice', quantity: 2, category: 'rice' },
{ name: 'brown rice', quantity: 1, category: 'rice' }
],
water: [
{ name: 'sparkle water', quantity: 1, category: 'water' },
{ name: 'still water', quantity: 1, category: 'water' }
],
tea: [
{ name: 'green tea', quantity: 1, category: 'water' }],
};
const sum = () => {
let quantity = {}
for (var property in groupedData) {
for (let i = 0; i < groupedData[property].length; i ) {
quantity[property] = quantity[property] ? quantity[property] : 0;
quantity[property] = groupedData[property][i].quantity;
}
}
return quantity;
};
console.log(sum());
<iframe name="sif4" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
You can also make use of Object.entries
, Array.forEach
and Array.reduce
to achieve this.
const groupedData = {
rice: [
{ name: 'white rice', quantity: 2, category: 'rice' },
{ name: 'brown rice', quantity: 1, category: 'rice' }
],
water: [
{ name: 'sparkle water', quantity: 1, category: 'water' },
{ name: 'still water', quantity: 1, category: 'water' }
],
tea: [
{ name: 'green tea', quantity: 1, category: 'water' }],
};
const sum = () => {
let quantity = {};
Object.entries(groupedData).forEach(([key, value]) => {
quantity[key] = value.reduce((acc, { quantity }) => acc = quantity, 0)
});
return quantity;
};
console.log(sum());
<iframe name="sif5" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
and as a one liner...
var result = Object.keys(groupedData).reduce((prev, key) => ({...prev,[key]: groupedData[key].reduce((total,item)=>total item.quantity,0)}),{});
console.log(result);
using Object.entries is perhaps more readable
var result2 = Object.entries(groupedData).reduce((prev, [k, v]) => ({...prev, [k]: v.reduce((total,item)=>total item.quantity,0)}),{});
console.log(result2);