Miodrag Sumaric
Miodrag Sumaric

Reputation: 45

How to form an array of nested arrays in my specific case?

I have a specific usecase where I want to combine all objects from an array into one new array. So I have a form in my website where users while booking are adding participants. They can add as many participants as they want. I save them in database as JSON and now I want to form a array of all participants so that I can show them all in the table.

So I first fetch all transactions from a specific listing which I get as an Array of objects and then I loop through them all and only get the transaction.attributes.protectedData.questions which holds the participants of each transaction.

So my transactions object looks like:

[
   {
      "type":"transaction",
      "attributes":{
         "createdAt":"2021-06-24T08:50:26.911Z",
         "protectedData":{
            "questions":[
               [
                  {
                     "question":"name",
                     "answer":"Mario North"
                  },
                  {
                     "question":"email",
                     "answer":"[email protected]"
                  }
               ]
            ],
            "ticketType":{
               "name":"Main entry",
               "quantity":1
            }
         }
      }
   },
   {
      "type":"transaction",
      "attributes":{
         "createdAt":"2021-06-24T08:48:57.646Z",
         "protectedData":{
            "questions":[
               [
                  {
                     "question":"name",
                     "answer":"John Adkins"
                  },
                  {
                     "question":"email",
                     "answer":"[email protected]"
                  }
               ],
               [
                  {
                     "question":"name",
                     "answer":"Thomas Smith"
                  },
                  {
                     "question":"email",
                     "answer":"[email protected]"
                  }
               ]
            ],
            "ticketType":{
               "name":"General entry",
               "quantity":2
            }
         }
      }
   }
]

So I need to loop through each transaction, then loop through questions and each new array in questions array is a new participant. In each participant I need to save the createdAt and ticketType values from transaction property.

So my final array/object needs to look like this:

[
   {
      "createdAt":"2021-06-24T08:50:26.911Z",
      "ticketType":"Main entry",
      "name":"Mario North",
      "email":"[email protected]"
   },
   {
      "createdAt":"2021-06-24T08:48:57.646Z",
      "ticketType":"General entry",
      "name":"John Adkins",
      "email":"[email protected]"
   },
   {
      "createdAt":"2021-06-24T08:48:57.646Z",
      "ticketType":"General entry",
      "name":"Thomas Smith",
      "email":"[email protected]"
   }
]

So I can get the list of participants with createdAt and ticketType added to each of them. But I don't know how can I get my question/answer to appear as my wanted object I posted upper. This is what I have:

export const denormalisedParticipantList = transactions => {
  let participants = [];

  transactions.map(transaction => {
    const createdAt = transaction.attributes.createdAt;
    const questions = transaction.attributes.protectedData?.questions;
    const ticketType = transaction.attributes.protectedData?.ticketType?.name;

    return questions.map(q => {
      // Form new participant object
      const participant = {
        createdAt,
        ticketType,
        ...Object.fromEntries(q.map(({ question, answer }) => [question, answer])),
      };

      // Push new participant
      participants.push(participant);
    });
  });

  return participants;
};

I've been trying to figure it out since last night and I can't make it work. Can anyone please help me figure out how can I make a final array from my transactions object, I would be extremly thankful.

Upvotes: 4

Views: 85

Answers (3)

ikhvjs
ikhvjs

Reputation: 5937

You can simply use reduce and map.

const data = [{ "type": "transaction", "attributes": { "createdAt": "2021-06-24T08:50:26.911Z", "protectedData": { "questions": [[{ "question": "name", "answer": "Mario North" }, { "question": "email", "answer": "[email protected]" }]], "ticketType": { "name": "Main entry", "quantity": 1 } } } }, { "type": "transaction", "attributes": { "createdAt": "2021-06-24T08:48:57.646Z", "protectedData": { "questions": [[{ "question": "name", "answer": "John Adkins" }, { "question": "email", "answer": "[email protected]" }], [{ "question": "name", "answer": "Thomas Smith" }, { "question": "email", "answer": "[email protected]" },{ "question": "gender", "answer": "male" }]], "ticketType": { "name": "General entry", "quantity": 2 } } } }]


const output = data.reduce(
  (a, b) => [
    ...a,
    ...b.attributes.protectedData.questions.map(e => ({
      createdAt: b.attributes.createdAt,
      ticketType: b.attributes.protectedData.ticketType.name,
      ...e.reduce((acc, cur) => ({ ...acc, [cur.question]: cur.answer }), {}),
    })),
  ],
  []
);

console.log(output);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 1

pilchard
pilchard

Reputation: 12909

Destructuring can be a powerful way of keeping track of what you are accessing in a complex object. Here with flatMap() to return a single flattened array and Object.fromEntries() to map the questions array to individual objects.

const input = [{ "type": "transaction", "attributes": { "createdAt": "2021-06-24T08:50:26.911Z", "protectedData": { "questions": [[{ "question": "name", "answer": "Mario North" }, { "question": "email", "answer": "[email protected]" }]], "ticketType": { "name": "Main entry", "quantity": 1 } } } }, { "type": "transaction", "attributes": { "createdAt": "2021-06-24T08:48:57.646Z", "protectedData": { "questions": [[{ "question": "name", "answer": "John Adkins" }, { "question": "email", "answer": "[email protected]" }], [{ "question": "name", "answer": "Thomas Smith" }, { "question": "email", "answer": "[email protected]" }]], "ticketType": { "name": "General entry", "quantity": 2 } } } }]

const result = input.flatMap((
  {
    attributes: {
      createdAt,
      protectedData: {
        questions,
        ticketType: { name: ticketType } }
    }
  }
) => (
  questions.map(p => ({
    createdAt,
    ticketType,
    ...Object.fromEntries(p.map(({ question, answer }) => [question, answer]))
  }))
));

console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 2

Michel Gisenaël
Michel Gisenaël

Reputation: 174

var array = []
data.forEach((element) => {
var object = { created: null,ticketType: null,name: null,email: null }
object.created = element.attributes.createdAt;
object.ticketType = element.attributes.protectedData.ticketType.name;
var tmp_data = element.attributes.protectedData.questions;
tmp_data.forEach((tmp) => {
    tmp.forEach((item) => {
        if(item.question == "name"){
            object.name = item.answer;
        }else{
            object.email = item.answer;
        }
    })
    array.push(object);
})
})

try this :)

Upvotes: 1

Related Questions