I have an array boxSize
that has a total count of boxes for small
and large
boxes. I would like to combine these 2 separate objects into one if they have the same date and warehouse name
For example here is the boxSize
array:
const boxSize = [
{
warehouse: 'NYC',
deliveryWeek: '2022-11-07',
boxSize: 'small',
total: 5
},
{
warehouse: 'NYC',
deliveryWeek: '2022-11-07',
boxSize: 'large',
total: 9
}
]
I attempted to loop through the array like this in the code snippet below:
const boxSize = [
{
warehouse: 'NYC',
deliveryWeek: '2022-11-07',
boxSize: 'small',
total: 5
},
{
warehouse: 'NYC',
deliveryWeek: '2022-11-07',
boxSize: 'large',
total: 9
}
]
var obj = {};
for(let i = 0; i < boxSize.length; i ){
var date = boxSize[i].deliveryWeek;
// Get previous date saved inside the result
var p_date = obj[date] || {};
// Merge the previous date with the next date
obj[date] = Object.assign(p_date, boxSize[i]);
}
// Convert to an array
var result = Object.values(obj);
console.log(result);
I am having trouble coming up with the logic and finding up examples to meet these requirements condition.
How can I end up with an array that looks something similar to this when the objects have the same warehouse
and deliveryWeek
:
const boxSize = [
{
warehouse: 'NYC',
deliveryWeek: '2022-11-07',
boxSizeSmall: 'small',
smallTotal: 5,
boxSizeLarge: 'large',
largeTotal: 9
}
]
console.log(boxSize)
CodePudding user response:
You could get a result like that by aggregating them with a map and then doing some transformations on the values like this:
const boxSize = [{warehouse:'NYC',deliveryWeek:'2022-11-07',boxSize:'small',total:5},{warehouse:'NYC',deliveryWeek:'2022-11-07',boxSize:'large',total:9}];
const keyFor = (item) => `${item.warehouse}:${item.deliveryWeek}`;
const map = new Map();
boxSize.forEach((box) => {
const key = keyFor(box);
if (!map.has(key)) map.set(key, []);
map.get(key).push(box);
});
const result = Array.from(map).map(([, values]) => ({
warehouse: values[0].warehouse,
deliveryWeek: values[0].deliveryWeek,
...values.reduce((obj, item) => ({
...obj,
["boxSize" item.boxSize[0].toUpperCase() item.boxSize.slice(1)]: item.boxSize,
[item.boxSize "Total"]: item.total,
}), {}),
}));
console.log(result);
but this is really complicated and it's hard to use the resulting object in practice. Also, duplicate entries will be overwritten by the latest entry... I recommend using an array in the resulting object to avoid all of these:
const boxSize = [{warehouse:'NYC',deliveryWeek:'2022-11-07',boxSize:'small',total:5},{warehouse:'NYC',deliveryWeek:'2022-11-07',boxSize:'large',total:9}];
const keyFor = (item) => `${item.warehouse}:${item.deliveryWeek}`;
const map = new Map();
boxSize.forEach((box) => {
const key = keyFor(box);
if (!map.has(key)) map.set(key, []);
map.get(key).push(box);
});
const result = Array.from(map).map(([, values]) => ({
warehouse: values[0].warehouse,
deliveryWeek: values[0].deliveryWeek,
details: values.map(({ boxSize, total }) => ({ boxSize, total })),
}));
console.log(result);
which is arguably easier to implement and use compared to the former.
CodePudding user response:
let boxSize = [
{
warehouse: 'NYC',
deliveryWeek: '2022-11-07',
boxSize: 'small',
total: 5
},
{
warehouse: 'NYC',
deliveryWeek: '2022-11-07',
boxSize: 'large',
total: 9
}
]
let combinedBoxes = [];
for(let i = 0; i < boxSize.length; i ){
let currentBox = boxSize[i];
let boxes = boxSize.filter(box => box.warehouse == currentBox.warehouse && box.deliveryWeek == currentBox.deliveryWeek)
let small = boxes.filter(box => box.boxSize == "small")[0]
let large = boxes.filter(box => box.boxSize == "large")[0]
combinedBoxes.push({
warehouse: currentBox.warehouse,
deliveryWeek: currentBox.deliveryWeek,
smallTotal: small.total,
largeTotal: large.total
})
boxSize = boxSize.filter(box => box.warehouse != currentBox.warehouse && box.deliveryWeek != currentBox.deliveryWeek)
}
console.log(combinedBoxes)