I am trying to create an object that will be filled with values from an existing object. In my case it should have as result per "Material" an object list with the "Code" and the "Quantity". In addition, if the "Material" and "Code" are the same, the "Quantity" should be summed up. I hope that you can see from my example what I mean. Thanks
const arr = [{
"Material": "123",
"Code": "AAA",
"Quantity": 1
}, {
"Material": "123",
"Code": "BBB",
"Quantity": 2
}, {
"Material": "123",
"Code": "BBB",
"Quantity": 2
}, {
"Material": "456",
"Code": "CCC",
"Quantity": 7
}]
var arrResult = [{
"Material": "123",
"CodeQuantity": [{
"Code": "AAA",
"Quantity": 1
}, {
"Code": "BBB",
"Quantity": 4
}]
}, {
"Material": "456",
"CodeQuantity": [{
"Code": "CCC",
"Quantity": 7
}]
}]
console.log(arr)
console.log("Result:", arrResult)
CodePudding user response:
An approach should consider breaking the OP's entire task into two separate ones.
Within an intermediate step one firstly does reduce
the list of material items into a map of (grouped) material items.
The final step does a map
-reduce
on the values
of the intermediate result, where the reduce
task is responsible for summing up a material's Code
specific Quantity
value ...
function collectTotalCodeQuantity(index, item) {
const { Code, Quantity } = item;
// access or create the `Code` specific code quantity item.
const codeQuantityItem = (index[Code] ??= { Code, Quantity: 0 });
// sum up a `Code` specific code quantity item's quantity value.
codeQuantityItem.Quantity = Quantity;
return index;
}
function createMaterialGroup(index, item) {
const { Material: materialValue, ...rest } = item;
// create the `CodeQuantity` key in a more generic way from the
// `rest` object which is ... `item` data without `Material` property.
const compoundKey = Object.keys(rest).join('');
// access or create the `Material` specific group.
const group = index[materialValue] ??= { Material: materialValue };
// access or create the `CodeQuantity` specific list.
const list = group[compoundKey] ??= [];
// push the `rest` object into the `CodeQuantity` specific list.
list.push(rest);
return index;
}
const materialDataItemList = [{
"Material": "123",
"Code": "AAA",
"Quantity": 1
}, {
"Material": "123",
"Code": "BBB",
"Quantity": 2
}, {
"Material": "123",
"Code": "BBB",
"Quantity": 2
}, {
"Material": "456",
"Code": "AAA",
"Quantity": 7
}];
const totalCodeQuantityItemList = Object
.values(
materialDataItemList.reduce(createMaterialGroup, {})
)
.map(materialGroup => {
materialGroup.CodeQuantity = Object.values(
materialGroup.CodeQuantity.reduce(collectTotalCodeQuantity, {})
);
return materialGroup;
});
console.log({ totalCodeQuantityItemList });
console.log(
'... intermediate process result ... map of (grouped) material items ...',
materialDataItemList.reduce(createMaterialGroup, {})
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
CodePudding user response:
Updated the solution to match your expectation. This this. Hope it solves your use case.
const arr = [{
"Material": "123",
"Code": "AAA",
"Quantity": 1
}, {
"Material": "123",
"Code": "BBB",
"Quantity": 2
}, {
"Material": "123",
"Code": "BBB",
"Quantity": 2
}, {
"Material": "456",
"Code": "CCC",
"Quantity": 7
}]
var arrResultExpected = [{
"Material": "123",
"CodeQuantity": [{
"Code": "AAA",
"Quantity": 1
}, {
"Code": "BBB",
"Quantity": 4
}]
}, {
"Material": "456",
"CodeQuantity": [{
"Code": "CCC",
"Quantity": 7
}]
}]
//console.log(arr)
//console.log("ExpecredResult:", arrResultExpected)
const materialIds = arr.map(a => a.Material);
//console.log(materialIds);
const dedupedMaterialIds = [...new Set(materialIds)]
//console.log(dedupedMaterialIds);
const needArr = dedupedMaterialIds.map(entry => {
const matchingEntries = arr.filter(arrEntry => entry === arrEntry.Material);
//console.log(matchingEntries);
var summedResult = [];
matchingEntries.reduce(function(res, value) {
if (!res[value.Code]) {
res[value.Code] = {
Quantity: 0,
Code: value.Code
};
summedResult.push(res[value.Code])
}
res[value.Code].Quantity = value.Quantity
return res;
}, {});
//console.log(summedResult);
return {
Material: entry,
CodeQuantity: [...summedResult]
};
});
console.log(needArr);
CodePudding user response:
try this
const arr = [{
"Material": "123",
"Code": "AAA",
"Quantity": 1
}, {
"Material": "123",
"Code": "BBB",
"Quantity": 2
}, {
"Material": "123",
"Code": "BBB",
"Quantity": 2
}, {
"Material": "456",
"Code": "CCC",
"Quantity": 7
}];
let group = arr.reduce((r, a) => {
r[a.Material] = [...r[a.Material] || [], a];
return r;
}, {});
var newArr = Object.keys(group).map(key => {
var elem = group[key];
var b = elem.map(e => {
return {
Code: e.Code,
Quantity: e.Quantity
}
});
var filteredArr = [];
b.map(i => {
var item = filteredArr.find(n => n.Code == i.Code);
if (item) {
item.Quantity = i.Quantity;
} else {
filteredArr.push(i);
}
})
return {
Material: key,
CodeQuantity: filteredArr
}
});
console.log(newArr);