Search code examples
javascriptobjectnested

Sum up two kind of values in nested Object by category1


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)


Solution

  • 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));