Group Objects by Multiple Properties in Array Then Sum Up Their Values

Group objects by multiple properties in array then sum up their values

Use Array#reduce with a helper object to group similar objects. For each object, check if the combined shape and color exists in the helper. If it doesn't, add to the helper using Object#assign to create a copy of the object, and push to the array. If it does, add it's values to used and instances.

var arr = [{"shape":"square","color":"red","used":1,"instances":1},{"shape":"square","color":"red","used":2,"instances":1},{"shape":"circle","color":"blue","used":0,"instances":0},{"shape":"square","color":"blue","used":4,"instances":4},{"shape":"circle","color":"red","used":1,"instances":1},{"shape":"circle","color":"red","used":1,"instances":0},{"shape":"square","color":"blue","used":4,"instances":5},{"shape":"square","color":"red","used":2,"instances":1}];
var helper = {};var result = arr.reduce(function(r, o) { var key = o.shape + '-' + o.color; if(!helper[key]) { helper[key] = Object.assign({}, o); // create a copy of o r.push(helper[key]); } else { helper[key].used += o.used; helper[key].instances += o.instances; }
return r;}, []);
console.log(result);

How to group and merge array entries and to sum-up values on multiple common (but not all) keys?

Just test both properties in the find() callback, and add both to the new object when pushing into acc.

const arr = [
{'ID':'1','Parent':'1','Member': '1','Code': '123','Subject': 'Org A','value': 0.3},
{'ID':'2','Parent':'1','Member': '1','Code': '124','Subject': 'Org A','value': 0.25},
{'ID':'3','Parent':'1','Member': '1','Code': '123','Subject': 'Org B','value': 0.45},
{'ID':'4','Parent':'1','Member': '2','Code': '125','Subject': 'Org A','value': 0.8},
{'ID':'5','Parent':'1','Member': '2','Code': '211','Subject': 'Org C','value': 0.3},
{'ID':'6','Parent':'1','Member': '3','Code': '221','Subject': 'Org B','value': 0.3},
{'ID':'7','Parent':'1','Member': '3','Code': '221','Subject': 'Org C','value': 0.25},
{'ID':'8','Parent':'1','Member': '3','Code': '234','Subject': 'Org A','value': 0.45},
{'ID':'9','Parent':'1','Member': '4','Code': '123','Subject': 'Org A','value': 0.8},
{'ID':'10','Parent':'2','Member': '5','Code': '123','Subject': 'Org D','value': 0.3},
{'ID':'11','Parent':'2','Member': '5','Code': '123','Subject': 'Org E','value': 0.3},
{'ID':'12','Parent':'2','Member': '6','Code': '125','Subject': 'Org E','value': 0.25},
{'ID':'13','Parent':'2','Member': '6','Code': '211','Subject': 'Org F','value': 0.45},
{'ID':'14','Parent':'2','Member': '6','Code': '221','Subject': 'Org F','value': 0.8},
{'ID':'15','Parent':'2','Member': '6','Code': '123','Subject': 'Org G','value': 0.3},
{'ID':'16','Parent':'3','Member': '7','Code': '124','Subject': 'Org H','value': 0.3},
{'ID':'17','Parent':'3','Member': '8','Code': '124','Subject': 'Org H','value': 0.25},
{'ID':'18','Parent':'3','Member': '9','Code': '123','Subject': 'Org I','value': 0.45},
{'ID':'19','Parent':'3','Member': '10','Code': '123','Subject': 'Org J','value': 0.8},
{'ID':'20','Parent':'3','Member': '10','Code': '211','Subject': 'Org I','value': 0.3},
{'ID':'21','Parent':'4','Member': '11','Code': '221','Subject': 'Org K','value': 0.3},
{'ID':'22','Parent':'4','Member': '11','Code': '234','Subject': 'Org K','value': 0.25},
{'ID':'23','Parent':'4','Member': '12','Code': '234','Subject': 'Org K','value': 0.45},
{'ID':'24','Parent':'4','Member': '12','Code': '123','Subject': 'Org L','value': 0.8},
{'ID':'25','Parent':'4','Member': '13','Code': '211','Subject': 'Org M','value': 0.3}
];

const summed = arr.reduce((acc, cur) => {
const item = acc.length > 0 && acc.find(({
Code, Parent
}) => Code === cur.Code && Parent == cur.Parent)
if (item) {
item.value += cur.value
} else acc.push({
Code: cur.Code,
Parent: cur.Parent,
value: cur.value
});
return acc
}, [])
console.log(arr); // not modified
console.log(summed)

How to group by(multiple key) and sum of multiple property values in javascript array (NodeJs)

You can do that with reduce and take Object.values of it:

var array = [ { Phase: "Phase 1", Step: "Step 1", Value1: "15", Value2: "5" }, { Phase: "Phase 1", Step: "Step 2", Value1: "20", Value2: "10" }, { Phase: "Phase 2", Step: "Step 1", Value1: "25", Value2: "15" }, { Phase: "Phase 2", Step: "Step 2", Value1: "30", Value2: "20" }, { Phase: "Phase 1", Step: "Step 1", Value1: "35", Value2: "25" }, { Phase: "Phase 1", Step: "Step 2", Value1: "40", Value2: "30" }, { Phase: "Phase 2", Step: "Step 1", Value1: "45", Value2: "35" }, { Phase: "Phase 2", Step: "Step 2", Value1: "50", Value2: "40" }];

var result = Object.values(array.reduce((acc, {Value1, Value2,...rest})=>{
const key = Object.values(rest).join('|');
acc[key] = acc[key] || {...rest, Value1:0,Value2:0};
acc[key].Value1+=+Value1;
acc[key].Value2+=+Value2;
return acc;
},{}));

console.log(result);

Group by and sum with multiple properties using Javascript

You could group with an object as has table and fin the nested values for grouping.

This approach uses a double grouping, one for the outer groups with the wanted properties and another for the valueId/value.

The outer grouping takes a joint key with the values for grouping, separated by a |. I generates a new object with the given keys and an empty array for the values.

The inner grouping takes place with the valueId and a seach for an object with this values. If not found, a new object is added to the values array.

Finally the value is added to the specific group.

function groupBy(data, keys) {
return Object.values(data.reduce((r, { metric, values }) => {
const key = keys.map(k => metric[k]).join('|');
r[key] = r[key] || { ...Object.fromEntries(keys.map(k => [k, metric[k]])), values: [] };
values.forEach(([valueId, value]) => {
let temp = r[key].values.find(q => q.valueId === valueId);
if (!temp) r[key].values.push(temp = { valueId, value: 0 });
temp.value += value;
});
return r;
}, {}));
}

const
dummyData = [{ metric: { id: "A", code: "00", advice: "123" }, values: [[123, 1], [332, 2]] }, { metric: { id: "A", code: "01", advice: "123" }, values: [[123, 5], [332, 3]] }, { metric: { id: "B", code: "01", advice: "123" }, values: [[123, 3]] }];

console.log(groupBy(dummyData, ['id']));
console.log(groupBy(dummyData, ['id', 'code']));
console.log(groupBy(dummyData, ['id', 'advice']));
.as-console-wrapper { max-height: 100% !important; top: 0; }

How to group by multiple values and sum an array of objects?

You can do something like the below, using vanilla JS:

var array = [
{ type: "alu", thick: 1, width: 1000, height: 2000, amount: 50 },
{ type: "alu", thick: 1, width: 1000, height: 2000, amount: 30 },
{ type: "alu", thick: 1.5, width: 1000, height: 2000, amount: 20 },
{ type: "metal", thick: 2, width: 1500, height: 3000, amount: 15 }
];

const res = [];

const process = () =>
array.forEach((r) => {
const found = res.find(
(a) =>
a.type == r.type &&
a.thick == r.thick &&
a.width == r.width &&
a.height == r.height
);
if (found) {
found.amount += r.amount;
} else {
res.push({ ...r });
}
});

process();
console.log(res);

Which returns:

[
{
"type": "alu",
"thick": 1,
"width": 1000,
"height": 2000,
"amount": 80
},
{
"type": "alu",
"thick": 1.5,
"width": 1000,
"height": 2000,
"amount": 20
},
{
"type": "metal",
"thick": 2,
"width": 1500,
"height": 3000,
"amount": 15
}
]

Alternatively you can use reduce:

const res = array.reduce((acc, el) => {
const found = acc.find(
(a) =>
a.type == el.type &&
a.thick == el.thick &&
a.width == el.width &&
a.height == el.height
);
if (found) {
found.amount += el.amount;
} else {
acc.push({ ...el });
}
return acc;
}, []);

console.log(res);

How to group an array of objects based on multiple keys in Javascript?

You could create an accumulator object with a new key for each unique combination of those 3 keys seperated by -. Then based on this new key merge the array using reduce. Use destructuring to separate the keys you need in the PickupTimeSlots to a rest variable. Then use Object.values to get the final array:

const slots=[{"WarehouseId":1,"ShippingCarrierId":1,"PostalCodeType":"ShipToCustomer","TimeStart":"1970-01-01T06:00:00.000Z","TimeEnd":"1970-01-01T15:59:00.000Z","PickupTimeSlot":"PM","DaysToAdd":0,"PickupTime":"1970-01-01T17:00:00.000Z"},{"WarehouseId":1,"ShippingCarrierId":1,"PostalCodeType":"ShipToCustomer","TimeStart":"1970-01-01T16:00:00.000Z","TimeEnd":"1970-01-01T23:59:00.000Z","PickupTimeSlot":"AM","DaysToAdd":1,"PickupTime":"1970-01-01T11:00:00.000Z"},{"WarehouseId":1,"ShippingCarrierId":1,"PostalCodeType":"ShipToCustomer","TimeStart":"1970-01-01T00:00:00.000Z","TimeEnd":"1970-01-01T05:59:00.000Z","PickupTimeSlot":"AM","DaysToAdd":0,"PickupTime":"1970-01-01T11:00:00.000Z"},{"WarehouseId":2,"ShippingCarrierId":2,"PostalCodeType":"ShipToCustomer","TimeStart":"1970-01-01T00:00:00.000Z","TimeEnd":"1970-01-01T15:59:00.000Z","PickupTimeSlot":"PM","DaysToAdd":0,"PickupTime":"1970-01-01T17:00:00.000Z"},{"WarehouseId":2,"ShippingCarrierId":2,"PostalCodeType":"ShipToCustomer","TimeStart":"1970-01-01T16:00:00.000Z","TimeEnd":"1970-01-01T23:59:00.000Z","PickupTimeSlot":"AM","DaysToAdd":1,"PickupTime":"1970-01-01T11:00:00.000Z"},{"WarehouseId":1,"ShippingCarrierId":3,"PostalCodeType":"ShipToDS","TimeStart":"1970-01-01T00:00:00.000Z","TimeEnd":"1970-01-01T15:59:00.000Z","PickupTimeSlot":"PM","DaysToAdd":0,"PickupTime":"1970-01-01T17:00:00.000Z"},{"WarehouseId":1,"ShippingCarrierId":3,"PostalCodeType":"ShipToDS","TimeStart":"1970-01-01T16:00:00.000Z","TimeEnd":"1970-01-01T23:59:00.000Z","PickupTimeSlot":"AM","DaysToAdd":1,"PickupTime":"1970-01-01T11:00:00.000Z"},{"WarehouseId":2,"ShippingCarrierId":4,"PostalCodeType":"ShipToDS","TimeStart":"1970-01-01T00:00:00.000Z","TimeEnd":"1970-01-01T15:59:00.000Z","PickupTimeSlot":"PM","DaysToAdd":0,"PickupTime":"1970-01-01T17:00:00.000Z"},{"WarehouseId":2,"ShippingCarrierId":4,"PostalCodeType":"ShipToDS","TimeStart":"1970-01-01T16:00:00.000Z","TimeEnd":"1970-01-01T23:59:00.000Z","PickupTimeSlot":"AM","DaysToAdd":1,"PickupTime":"1970-01-01T11:00:00.000Z"},{"WarehouseId":1,"ShippingCarrierId":5,"PostalCodeType":"ShipToDS","TimeStart":"1970-01-01T00:00:00.000Z","TimeEnd":"1970-01-01T16:22:00.000Z","PickupTimeSlot":"PM","DaysToAdd":0,"PickupTime":"1970-01-01T17:00:00.000Z"},{"WarehouseId":1,"ShippingCarrierId":5,"PostalCodeType":"ShipToDS","TimeStart":"1970-01-01T16:23:00.000Z","TimeEnd":"1970-01-01T23:59:00.000Z","PickupTimeSlot":"AM","DaysToAdd":1,"PickupTime":"1970-01-01T11:00:00.000Z"},{"WarehouseId":2,"ShippingCarrierId":6,"PostalCodeType":"ShipToDS","TimeStart":"1970-01-01T00:00:00.000Z","TimeEnd":"1970-01-01T15:59:00.000Z","PickupTimeSlot":"PM","DaysToAdd":0,"PickupTime":"1970-01-01T17:00:00.000Z"},{"WarehouseId":2,"ShippingCarrierId":6,"PostalCodeType":"ShipToDS","TimeStart":"1970-01-01T16:00:00.000Z","TimeEnd":"1970-01-01T23:59:00.000Z","PickupTimeSlot":"AM","DaysToAdd":1,"PickupTime":"1970-01-01T11:00:00.000Z"},{"WarehouseId":1,"ShippingCarrierId":1,"PostalCodeType":"ShipToDS","TimeStart":"1970-01-01T06:00:00.000Z","TimeEnd":"1970-01-01T15:59:00.000Z","PickupTimeSlot":"PM","DaysToAdd":0,"PickupTime":"1970-01-01T17:00:00.000Z"},{"WarehouseId":1,"ShippingCarrierId":1,"PostalCodeType":"ShipToDS","TimeStart":"1970-01-01T16:00:00.000Z","TimeEnd":"1970-01-01T23:59:00.000Z","PickupTimeSlot":"AM","DaysToAdd":1,"PickupTime":"1970-01-01T11:00:00.000Z"},{"WarehouseId":1,"ShippingCarrierId":1,"PostalCodeType":"ShipToDS","TimeStart":"1970-01-01T00:00:00.000Z","TimeEnd":"1970-01-01T05:59:00.000Z","PickupTimeSlot":"AM","DaysToAdd":0,"PickupTime":"1970-01-01T11:00:00.000Z"},{"WarehouseId":2,"ShippingCarrierId":2,"PostalCodeType":"ShipToDS","TimeStart":"1970-01-01T00:00:00.000Z","TimeEnd":"1970-01-01T15:59:00.000Z","PickupTimeSlot":"PM","DaysToAdd":0,"PickupTime":"1970-01-01T17:00:00.000Z"},{"WarehouseId":2,"ShippingCarrierId":2,"PostalCodeType":"ShipToDS","TimeStart":"1970-01-01T16:00:00.000Z","TimeEnd":"1970-01-01T23:59:00.000Z","PickupTimeSlot":"AM","DaysToAdd":1,"PickupTime":"1970-01-01T11:00:00.000Z"}]
const merged = slots.reduce((r, { WarehouseId, ShippingCarrierId, PostalCodeType,...rest }) => { const key = `${WarehouseId}-${ShippingCarrierId}-${PostalCodeType}`; r[key] = r[key] || { WarehouseId, ShippingCarrierId, PostalCodeType, PickupTimeSlots: [] }; r[key]["PickupTimeSlots"].push(rest) return r;}, {})
const timeTable = Object.values(merged)console.log(timeTable)

how to group and sum data in foreach javascript

you can use reduce usually for these grouping problems. I'm taking the combination of code and date to group. something like "8|2022-03-24".

This is how the intermediate object will look like

{
8|2022-03-24: {
code: 8,
date: "2022-03-24",
total: 12
},
8|2022-03-25: {
code: 8,
date: "2022-03-25",
total: 2
},
9|2022-03-24: {
code: 9,
date: "2022-03-24",
total: 4
},
9|2022-03-25: {
code: 9,
date: "2022-03-25",
total: 3
}
}

From that object I'm taking the values using Object.values

const data = [
{code: 8, date:"2022-03-24", total:4},
{code: 8, date:"2022-03-24", total:8},
{code: 8, date:"2022-03-25", total:2},
{code: 9, date:"2022-03-24", total:4},
{code: 9, date:"2022-03-25", total:2},
{code: 9, date:"2022-03-25", total:1},]

let grouped = Object.values(data.reduce((acc,{code,date,total})=>{
acc[code+'|'+date] = acc[code+'|'+date] || {code,date,total:0}
acc[code+'|'+date].total+=total
return acc;
},{}))

console.log(grouped)

Group array by two different keys and sum values

If I understand correctly you want to sum all values per month per year. I guess this will work.

// Generate random data.
const genData = () => {
const d = [];
for(let i =0; i < 1000; i++) {
d.push({
year: Math.round(Math.random() * 10) + 2001,
month: Math.round(Math.random() * 12),
amount: Math.round(Math.random() * 100) + 100
})
}
return d;
};

// Sum all data per month per year
const sumData = (d) => {
const summed = {};
for(const {year,month,amount} of d) {
// By using a unique key for each year/month combi you can easily access the
// intermedeiate result and add another value.
const key = year + '/' + month;

// If it does not yet exist, create an empty record for this year/month
if(!(key in summed)) {
summed[key] = {year,month, sum:0, values:[]};
}

// Grab the intermediate values and add amount to sum and to values
summed[key].values.push(amount)
summed[key].sum += amount;
}
return Object.values(summed);
};

// Run all
const d = genData();
console.log(d);
console.log(sumData(d));

Reduce multiple properties in array of array of objects and omit other properties using Ramda

One Ramda approach:

const convert = pipe (
transpose,
map (xs => ({
index: xs [0] .index,
value: xs .reduce ((a, {value}) => a + Number (value), 0),
participants: sum (pluck ('participants') (xs))
}))
)

const data = [[{index: 320, blocks: 2, value: "31011784785", participants: 1222, cost: "1286828506"}, {index: 319, blocks: 0, value: "111306385", participants: 18, cost: "0"}, {index: 318, blocks: 0, value: "14550473", participants: 10, cost: "0"}], [{index: 320, blocks: 1, value: "7089001673", participants: 492, cost: "648196615"}, {index: 319, blocks: 0, value: "13551137", participants: 8, cost: "0"}, {index: 318, blocks: 0, value: "11499815", participants: 5, cost: "0"}], [{index: 320, blocks: 1, value: "408900161", participants: 200, cost: "648196615"}, {index: 319, blocks: 0, value: "23551231", participants: 10, cost: "0"}, {index: 318, blocks: 0, value: "104324219", participants: 5, cost: "0"}]]

console .log (convert (data))
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.28.0/ramda.min.js"></script>
<script> const {pipe, transpose, map, sum, pluck, reduce, applySpec} = R </script>


Related Topics



Leave a reply



Submit