Reputation: 544
Have a problem with arrays in JS. Can't convert from one array to another and i was trying forEach, map, filter, everything what can do with arrays but i can't do this:( Maybe there is another method for that? I was in trying around 3 hours...
How to convert from this array:
[
{
"id": 1,
"question": "Do you want to walk?",
"answers": [
{
"id": 1,
"answer": "Yes"
}
]
},
{
"id": 1,
"question": "Do you want to walk?",
"answers": [
{
"id": 2,
"answer": "No"
}
]
},
{
"id": 1,
"question": "Do you want to walk?",
"answers": [
{
"id": 3,
"answer": "Maybe"
}
]
},
{
"id": 1,
"question": "Do you want to walk?",
"answers": [
{
"id": 4,
"answer": "Never"
}
]
}
]
To this:
[
{
"id": 1,
"question": "Do you want to walk?",
"answers": [
{
"id": 1,
"answer": "Yes"
},
{
"id": 2,
"answer": "No"
},
{
"id": 3,
"answer": "Maybe"
},
{
"id": 4,
"answer": "Never"
}
]
}
]
Upvotes: 0
Views: 46
Reputation: 8239
Simply use Array.reduce()
to create a map based on id and use Object.values()
on the map to get the desired result:
let arr = [ { "id": 1, "question": "Do you want to walk?", "answers": [ { "id": 1, "answer": "Yes" } ] }, { "id": 1, "question": "Do you want to walk?", "answers": [ { "id": 2, "answer": "No" } ] }, { "id": 1, "question": "Do you want to walk?", "answers": [ { "id": 3, "answer": "Maybe" } ] }, { "id": 1, "question": "Do you want to walk?", "answers": [ { "id": 4, "answer": "Never" } ] } ];
let result = Object.values(arr.reduce((acc,obj)=>{
acc[obj.id] = acc[obj.id] || Object.assign({},obj);
acc[obj.id].answers = (acc[obj.id].answers || []).concat(obj.answers);
return acc;
},{}));
console.log(result);
Upvotes: 2
Reputation: 5556
So you want to merge all the objects that have the same ID such that the answers array is a list of the answers from all the objects? This sounds like a job for Array.reduce
:) Reduce will iterate through the full array and output a new value based on how a callback function manipulates that output value at each iteration.
arr.reduce((output, currentValue) => {
const existing = output.find(element => {
return element.id === currentValue.id;
});
if (existing) {
existing.answers.push(...currentValue.answers);
}
else {
output.push(currentValue);
}
return output;
}, []);
Note I'm using the spread operator ...currentValue.answers
here to spread the answers array out into multiple parameters to be pushed.
Upvotes: 2