Home > Net >  Combining objects if condition matches
Combining objects if condition matches

Time:11-08

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)

  • Related