skip to Main Content

It would be highly appreciated if you could help me out regarding nested JavaScript object. I would like to create a new object by summing up two values, price and quantity, by category in the nested object, "objToBeSumUp". It is so hard to sum up two values at the same time, at least I can create the for loop to sum up one value as mentioned in My halfway code below though.

Also, we would like to sort the object by total price in descending order.

Object to be sum up:

const objToBeSumUp ={
    0: {
        value: {
            category:{
                value: a
            },
            price:{
                value: 500
            },
            quantity:{
                value: 5
            }
        }
    },
    1: {
        value: {
            category:{
                value: a
            },
            price:{
                value: 300
            },
            quantity:{
                value: 3
            }
        }
    },
    2: {
        value: {
            category:{
                value: b
            },
            price:{
                value: 800
            },
            quantity:{
                value: 8
            }
        }
    },
    3: {
        value: {
            category:{
                value: b
            },
            price:{
                value: 400
            },
            quantity:{
                value: 4
            }
        }
    }
}

Expected Object:

const objExpected = {
    0: {
        value: {
            category:{
                value: b
            },
            totalPrice:{
                value: 1200
            },
            totalQuantity:{
                value: 12
            }
        }
    },
    1: {
        value: {
            category:{
                value: a
            },
            totalPrice:{
                value: 800
            },
            totalQuantity:{
                value: 8
            }
        }
    },
};

My halfway code:

const objExpected = {};
for (let i = 0; i < objToBeSumUp.length; i++) {
    const category = objToBeSumUp[i].value['category'].value;
    if (!objExpected[category]) {
      objExpected[category] = 0;
    }
    // Summing prices up
    const price = objToBeSumUp[i].value['price'].value;
    objExpected[category] += parseInt(price)

2

Answers


  1. You can just sort the array by totalPrice in descending order.

    Reduce the sorted array back into the expected object format, preserving the order from the sorting step.

    and you should have summed up OBJs in the expected format

    Note:

    console.log(JSON.stringify(objExpected, null, 2));

    is for properly displaying the object in the console because with regular console.log(objExpected) you might see the output:

    Category: [Object]

    Price: [Object]

    const objToBeSumUp = {
        0: {
            value: {
                category: { value: 'a' },
                price: { value: 500 },
                quantity: { value: 5 }
            }
        },
        1: {
            value: {
                category: { value: 'a' },
                price: { value: 300 },
                quantity: { value: 3 }
            }
        },
        2: {
            value: {
                category: { value: 'b' },
                price: { value: 800 },
                quantity: { value: 8 }
            }
        },
        3: {
            value: {
                category: { value: 'b' },
                price: { value: 400 },
                quantity: { value: 4 }
            }
        }
    };
    
    const summedValues = {};
    
    // Summing up prices and quantities by category
    Object.values(objToBeSumUp).forEach(item => {
        const category = item.value.category.value;
        const price = item.value.price.value;
        const quantity = item.value.quantity.value;
    
        if (!summedValues[category]) {
            summedValues[category] = { totalPrice: 0, totalQuantity: 0 };
        }
    
        summedValues[category].totalPrice += price;
        summedValues[category].totalQuantity += quantity;
    });
    
    // Convert summedValues object to an array, sort by totalPrice, and convert back to the expected object format
    const sortedArray = Object.entries(summedValues).sort((a, b) => b[1].totalPrice - a[1].totalPrice);
    
    const objExpected = sortedArray.reduce((acc, [category, { totalPrice, totalQuantity }], index) => {
        acc[index] = {
            value: {
                category: { value: category },
                totalPrice: { value: totalPrice },
                totalQuantity: { value: totalQuantity }
            }
        };
        return acc;
    }, {});
    
    console.log(JSON.stringify(objExpected, null, 2));
    
    Login or Signup to reply.
    1. calc the sums with Array::reduce into an array
    2. sort values by the price
    3. convert the array into the final format (converting into an object could skipped)
    let result = Object.values(objToBeSumUp).reduce((r, {value:{category, price, quantity}}) => {
      const cat = r[category.value] ??= [0, 0, category.value];
      cat[0] += price.value, cat[1] += quantity.value;
      return r;
    }, {});
    
    result = Object.values(result).sort(([a], [b]) => b - a).map(cat => ({value:{category:{value: cat[2]}, totalPrice:{value: cat[0]}, totalQuantity:{value: cat[1]}}}));
    
    result = Object.fromEntries([...result.entries()]);
    
    console.log(result);
    <script>
    const a = 'cat1';
    const b = 'cat2';
    const objToBeSumUp={0:{value:{category:{value:a},price:{value:500},quantity:{value:5}}},1:{value:{category:{value:a},price:{value:300},quantity:{value:3}}},2:{value:{category:{value:b},price:{value:800},quantity:{value:8}}},3:{value:{category:{value:b},price:{value:400},quantity:{value:4}}}};
    </script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search