Group nested array of objects

Ayoub k

I have the following object:

const attributes = [
    {
        id: "a",
        values: [
            {
                value: [
                    {
                        _id: "aa",
                        value: "1500"
                    },
                    {
                        _id: "ab",
                        value: "580"
                    }
                ]
            },
            {
                value: [
                    {
                        _id: "aa",
                        value: "400"
                    }
                ]
            }
        ]
    },
    {
        id: "a",
        values: [
            {
                value: [
                    {
                        _id: "aa",
                        value: "420"
                    },
                    {
                        _id: "ab",
                        value: "300"
                    }
                ]
            },
            {
                value: [
                    {
                        _id: "aa",
                        value: "480"
                    },
                    {
                        _id: "ab",
                        value: "1000"
                    }
                ]
            },
            {
                value: [
                    {
                        _id: "aa",
                        value: "880"
                    },
                    {
                        _id: "ab",
                        value: "740"
                    }
                ]
            }
        ]
    },
    {
        id: "b",
        values: [
            {
                value: [
                    {
                        _id: "ba",
                        value: "1500"
                    },
                    {
                        _id: "bb",
                        value: "580"
                    }
                ]
            },
            {
                value: [
                    {
                        _id: "ba",
                        value: "400"
                    }
                ]
            }
        ]
    },
];

I want to group the data based on attribute id and value _id, so I can have the following object in return:

[
    {
        id: "a",
        values: [
            {
                value: [
                    {
                        _id: "aa",
                        values: ["1900", "1780"]
                    },
                    {
                        _id: "ab",
                        values: ["580", "2040"]
                    }
                ]
            }
        ]
    },
    {
        id: "b",
        values: [
            {
                value: [
                    {
                        _id: "ba",
                        values: ["1900"]
                    },
                    {
                        _id: "bb",
                        values: "[580"]
                    }
                ]
            },
        ]
    },
];

If the result doesn't make sense I can explain more. Anyway, I tried to attempt the result by doing the following but it doesn't work as expected and I'm sure there's a cleaner way to do so.

let newAttributes = [];
attributes.forEach(attribute => {
    let currentAttribute = { id: attribute.id, values: attribute.values[0] };
    attribute.values.shift();
    attribute.values.forEach(attributeValues => {
        attributeValues.value.forEach(vl => {
            var values = currentAttribute.values.value.find(vl2 => vl2._id === vl._id);
            if (values && attribute.id === currentAttribute.id) {
                if (!values.values) {
                    values.values = [];
                }
                values.values.push(vl.value);
            }
        });
    });
    newAttributes.push(attributes);
});

newAttributes.forEach(attribute => {
    attribute.values.value.forEach(vl => {
        if (vl.values) {
            vl.values.push(vl.value);
        } else {
            vl.values = [vl.value]
        }
        delete vl.value;
    });
    attribute.values.value.forEach(vl => {
        vl.values = vl.values.reduce((a, b) => {
            return Number(a) + Number(b);
        }, 0);
         vl.values =  [vl.values.toString()]
    });
});

console.log(newAttributes);

EDIT:

Explanation: let's take an example for the attribute id = 'a' and value _id = 'aa':

For the first attribute with id = 'a', we have two values with _id = 'aa', one has 1500 and the other has 400, we do the sum of those two values we got 1900, then we have another attribute with id = 'a' with 3 values with _id = 'aa', with values 420, 480 and 880, the sum of those values is 1780, we push that sum in the values with _id = 'aa' of the firt attribute with id = 'a'

Bahador Raghibizadeh

const attributes = [
    {
        id: "a",
        values: [
            {
                value: [
                    {
                        _id: "aa",
                        value: "1500"
                    },
                    {
                        _id: "ab",
                        value: "580"
                    }
                ]
            },
            {
                value: [
                    {
                        _id: "aa",
                        value: "400"
                    }
                ]
            }
        ]
    },
    {
        id: "a",
        values: [
            {
                value: [
                    {
                        _id: "aa",
                        value: "420"
                    },
                    {
                        _id: "ab",
                        value: "300"
                    }
                ]
            },
            {
                value: [
                    {
                        _id: "aa",
                        value: "480"
                    },
                    {
                        _id: "ab",
                        value: "1000"
                    }
                ]
            },
            {
                value: [
                    {
                        _id: "aa",
                        value: "880"
                    },
                    {
                        _id: "ab",
                        value: "740"
                    }
                ]
            }
        ]
    },
    {
        id: "b",
        values: [
            {
                value: [
                    {
                        _id: "ba",
                        value: "1500"
                    },
                    {
                        _id: "bb",
                        value: "580"
                    }
                ]
            },
            {
                value: [
                    {
                        _id: "ba",
                        value: "400"
                    }
                ]
            }
        ]
    },
];

let newStructure = 
	attributes.map(attr => {
		let tempValues = {};
		attr.values.forEach((value, index)=> { 
			value.value.forEach((v)=>{
				if(typeof tempValues[v._id] == "undefined")
					tempValues[v._id] = 0;
				tempValues[v._id] += +v.value

			})
		})
		return {
			id: attr.id,
			values: tempValues
		}

}).reduce((accumulator, currentValue)=>{
	if(typeof accumulator[currentValue.id] == "undefined")
		accumulator[currentValue.id] = { id: currentValue.id, values: {} };
	Object.keys(currentValue.values).forEach( valueKey =>{
		if(typeof accumulator[currentValue.id].values[valueKey] == "undefined")
				accumulator[currentValue.id].values[valueKey] = [currentValue.values[valueKey]];
		else
				accumulator[currentValue.id].values[valueKey].push(currentValue.values[valueKey]);
	})
	
	return accumulator
},{})

newStructure = Object.keys(newStructure).map(itemKey => {
	return {
		id: itemKey,
		values: {
			value: Object.keys(newStructure[itemKey].values).map(valueKey => {
				return  {
					_id: valueKey,
					value: newStructure[itemKey].values[valueKey]
				}
			})
		}
	}
});

console.log(newStructure)

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Group objects inside the nested array

Group an array of nested objects by 'sector' keyword - Javascript

JavaScript: How to Group Array of Objects with Nested Properties?

Group array of objects nested by several groupBy functions

unwind and group for the nested array objects in mongodb

lodash group array of nested objects by key

Iterate over array of objects for group by Key and nested array of objects

How to group objects by nested child objects of array in array

How to Group Array of Nested Objects into Multiple Arrays by Nested Value

Group array of objects by common keys, merging nested property into array

How to group an array of objects by key and sums a nested object property

javascript group a nested array of objects by child object value

Group an array of objects by unix time while filtering on nested values

Create nested array of objects and Group based on 2 column in javascript

How to group an array of nested objects by three different properties in JS

Group nested objects with reduce

Array of objects nested in an Array of objects

Group array of objects inside nested Array and add its total to a new Array

Filtering array of objects and nested objects

Convert nested objects into an array of objects

Sorting nested array of objects

Accessing array with nested objects

Flatten an array with nested objects

Destructuring nested objects in an array

Swagger Nested Array of Objects

Flatten array of nested objects

Typing nested array of objects

Transform nested array of objects

Sorting array of nested objects