I'm looking to create a nested array based on reading a flat array. An example of the flat array I am reading is this:
const flatItems = [
{
"code": "CODE1",
"title": "Title 1",
"question": "Question 1",
"order": 0,
},
{
"code": "CODE2",
"title": "Title 2",
"question": "Question 2",
"order": 1,
},
{
"code": "CODE3",
"title": "Title 3",
"question": "Question 3",
"order": 2,
},
{
"code": "CODE4",
"title": "Title 4",
"question": "Question 4",
"order": 3,
},
];
And ideally I would like to place this into groups of 'Yes's and 'No's. The flat array is already in the correct order. There will only ever be one item in the 'Yes's but can have many in the 'No's depending on any conditions.
const treeItems = {
question: "Question 1",
options: [
{
value: "Yes",
items: [
{
code: "CODE1",
title: "Title 1"
}
]
},
{
value: "No",
question: "Question 2"
options: [
{
value: "Yes",
items: [
{
code: "CODE2",
title: "Title 2"
}
]
},
{
value: "No",
items: [
{
code: "CODE3",
title: "Title 3"
},
{
code: "CODE4",
title: "Title 4"
}
]
}
]
}
]
};
I am aware that reduce may be the best approach here, but would anyone have any good examples or recommended practices as how I should go about doing this?
If you want to group these items use "Yes" and "No" as the properties of the final object. Using Array.reduce() sounds solid in this case.
Not sure how you want to group because your JSON is inconsistent.
const flatItems = [
{
"code": "CODE1",
"title": "Title 1",
"question": "Question 1",
"order": 0,
},
{
"code": "CODE2",
"title": "Title 2",
"question": "Question 2",
"order": 1,
},
{
"code": "CODE3",
"title": "Title 3",
"question": "Question 3",
"order": 2,
},
{
"code": "CODE4",
"title": "Title 4",
"question": "Question 4",
"order": 3,
},
];
const groupedObject = flatItems.reduce((tmpGroupedObject, item) => {
const groupingProperty = item.order < 2 ? "Yes" : "No"; /// grouping decision
if (!Array.isArray(tmpGroupedObject[groupingProperty])) {
tmpGroupedObject[groupingProperty] = []; /// make Obj["Yes"] an array
}
tmpGroupedObject[groupingProperty].push(item);
return tmpGroupedObject;
}, {});
console.log(groupedObject);
As mentioned in the comments, I'm confused by the requested output. I especially don't understand why CODE3 and CODE4 are on the same level, and not nested as another Yes/No pair. But we can write a fairly simple recursion to do that:
const convert = ([{code, title, question} = {}, ...items]) => ({
question,
options: [
{value: "Yes", items: [{code, title}]},
{value: "No", ... (items .length < 3 ? {items: items .map (({code, title}) => ({code, title}))} : convert (items))}
]
})
const flatItems = [{code: "CODE1", title: "Title 1", question: "Question 1", order: 0}, {code: "CODE2", title: "Title 2", question: "Question 2", order: 1}, {code: "CODE3", title: "Title 3", question: "Question 3", order: 2}, {code: "CODE4", title: "Title 4", question: "Question 4", order: 3}]
console .log (
convert (flatItems)
)
.as-console-wrapper {max-height: 100% !important; top: 0}
However by changing < 3 to < 2, we get what I think of as a much more logical grouping:
const convert = ([{code, title, question} = {}, ...items]) => ({
question,
options: [
{value: "Yes", items: [{code, title}]},
{value: "No", ... (items .length < 2 ? {items: items .map (({code, title}) => ({code, title}))} : convert (items))}
]
})
const flatItems = [{code: "CODE1", title: "Title 1", question: "Question 1", order: 0}, {code: "CODE2", title: "Title 2", question: "Question 2", order: 1}, {code: "CODE3", title: "Title 3", question: "Question 3", order: 2}, {code: "CODE4", title: "Title 4", question: "Question 4", order: 3}]
console .log (
convert (flatItems)
)
.as-console-wrapper {max-height: 100% !important; top: 0}
I hope one of these does what you want.
Also, again, welcome to StackOverflow. Next time, please be sure to post your own attempted solution in the question. Even if it's not working properly, we can often either help you fix it, or explain why it's headed down the wrong path altogether.