skip to Main Content

I’m trying to merge an array of object by removing the ones which have the same code attribute and computing its times attribute.

given the following array:

let itemsTimes = [
    {
        item: {
            code: '0.05'
        },
        times: 1
    },
    {
        item: {
            code: '0.01'
        },
        times: 1
    },
    {
        item: {
            code: '0.02'
        },
        times: 1
    },
    {
        item: {
            code: '0.01'
        },
        times: 1
    },
    {
        item: {
            code: '0.02'
        },
        times: 2
    }
];

and the following code:

let mergedItemTimes = [];

itemsTimes.forEach((itemTime, i) => {
    let j = i + 1
    if ((itemsTimes[j])) {
        itemsTimes.forEach((_, j) => {
            if (itemTime.item.code === itemsTimes[j].item.code) {
                itemTime.times += itemsTimes[j].times
                itemsTimes.splice(j, 1)
            }
        })
    }
    mergedItemTimes.push(itemTime)
})

The expected output it’ll be:

[
    { item: { code: '0.05' }, times: 1 },
    { item: { code: '0.01' }, times: 2 },
    { item: { code: '0.02' }, times: 3 },
]

but it’s giving me:

[
    { item: { code: '0.05' }, times: 2 },
    { item: { code: '0.02' }, times: 4 },
]

Thanks in advance.

2

Answers


  1. As you call splice on an array you are iterating, that loop will not visit the next element, because that element shifted to the previous index, and the iteration continues at the next index.

    One of the common ways to do this, is with reduce — not mutating the original objects or array:

    const itemsTimes = [{item: {code: '0.05'},times: 1},{item: {code: '0.01'},times: 1},{item: {code: '0.02'},times: 1},{item: {code: '0.01'},times: 1},{item: {code: '0.02'},times: 2}];
    const mergedItemTimes = Object.values(
        itemsTimes.reduce((acc, { item: { code }, times }) => {
            (acc[code] ??= { item: { code }, times: 0 }).times += times;
            return acc;
        }, {})
    );
    console.log(mergedItemTimes);
    Login or Signup to reply.
  2. I think you are looking for the sum of times where item.code being the key.

       const summary = itemsTimes.reduce((acc, curr) => {
         const accIndex = acc.findIndex((accItem) => accItem.item.code === curr.item.code);
         if (accIndex === -1)
            acc.push(curr);
         if (accIndex >= 0)
            acc.at(accIndex).times += curr.times;
         return acc;
       }, []);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search