Reputation: 45
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
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
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
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