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'
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.
Comments