Marty
Marty

Reputation: 544

Convert array of objects to another

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

Answers (2)

amrender singh
amrender singh

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

IceMetalPunk
IceMetalPunk

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

Related Questions