Reputation: 87
Good morning, I would like to implement an algorithm that generates a node at each loop. If the node satisfies the condition, then it adds a child to it which contains a node with children if it satisfies the condition, etc.
I have an entry like below :
{
id: 1,
entitled: "first question",
questions: [
{
id: 1,
entitled: "Do you have a car ?",
answers: [
{ id: 1, entitled: "Yes", conditionalSection: 2 },
{ id: 2, entitled: "No", conditionalSection: 3 },
],
},
],
},
{
id: 2,
entitled: "section yes",
questions: [
{
id: 1,
entitled: "Do you have an electric car ?",
answers: [
{ id: 1, entitled: "Yes", conditionalSection: 4 },
{ id: 2, entitled: "No", conditionalSection: 4 },
],
},
],
},
{
id: 3,
entitled: "section no",
questions: [
{
id: 1,
entitled: "Do you have a bicycle ?",
answers: [
{ id: 1, entitled: "Yes", conditionalSection: 4 },
{ id: 2, entitled: "No", conditionalSection: 4 },
],
}
],
},
{
id: 4,
entitled: "end",
questions: [
{
id: 1,
entitled: "Do you have any comments ?",
}
],
},
];
and the output :
{
name: "Do you have a car ?",
children: [
{
name: "Yes",
children: [
{
name: "Do you have an electric car ?",
children: [
{ name: "Yes", children: [{ name: "Do you have any comments ?" }] },
{ name: "No", children: [{ name: "Do you have any comments ?" }] },
],
},
],
},
{
name: "No",
children: [
{
name: "Do you have a bicycle ?",
children: [
{ name: "Yes", children: [{ name: "Do you have any comments ?" }] },
{ name: "No", children: [{ name: "Do you have any comments ?" }] },
],
},
],
},
],
};
I tried to do something like this (but i'm lost) :
const output = []
const prototype = { name: "", children: [] };
sections.forEach((section, index) => {
prototype[index] = prototype;
});
sections.forEach((section, index) => {
let next = prototype;
section.questions.forEach((question, index) => {
let now = next;
next = prototype;
question.answers((answer, index) => {
if (answer.conditionalSection!==null){
output.push(next)
}
});
});
});
Upvotes: 0
Views: 464
Reputation: 386868
You could take some functions for getting questions and answers for a nested result.
This approach uses an object as reference to the objects of the first level and omits children.
var data = [{ id: 1, entitled: "first question", questions: [{ id: 1, entitled: "Do you have a car ?", answers: [{ id: 1, entitled: "Yes", conditionalSection: 2 }, { id: 2, entitled: "No", conditionalSection: 3 }] }] }, { id: 2, entitled: "section yes", questions: [{ id: 1, entitled: "Do you have an electric car ?", answers: [{ id: 1, entitled: "Yes", conditionalSection: 4 }, { id: 2, entitled: "No", conditionalSection: 4 }] }] }, { id: 3, entitled: "section no", questions: [{ id: 1, entitled: "Do you have a bicycle ?", answers: [{ id: 1, entitled: "Yes", conditionalSection: 4 }, { id: 2, entitled: "No", conditionalSection: 4 }] }] }, { id: 4, entitled: "end", questions: [{ id: 1, entitled: "Do you have any comments ?" }] }],
children = {},
references = data.reduce((r, o) => {
r[o.id] = o;
o.questions.forEach(({ answers = [] }) => answers.forEach(o => {
if ('conditionalSection' in o) children[o.conditionalSection] = true;
}));
return r;
}, {}),
getReference = k => (references[k].questions || []).map(mapQuestions),
mapQuestions = ({ entitled: name, answers }) =>
({ name, ...(answers && { children: answers.map(mapAnswers) }) }),
mapAnswers = ({ entitled: name, conditionalSection: k }) =>
({ name, ...(k in references && { children: getReference(k) }) }),
result = Object.keys(references)
.filter(k => !(k in children))
.flatMap(getReference);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 1