I have a flat object and an array from which I need to construct a tree-like object.
choices: ['choice1', 'choice2', 'choice3'];
items: [
{
choice1: 'taste',
choice2: 'good',
choice3: 'green-lemon'
},
{
choice1: 'taste',
choice2: 'bad',
choice3: 'green-lemon'
}
];
The array describes the level at which each choice will come in the tree. I do not know how many choices, items or levels there will be later.
How do I get the following object:
output: {
taste: {
good: {
green-lemon:1
},
bad: {
green-lemon:1
}
}
}
I need to get an object describing how many items there are on each level. In this example this is choice1: 1;
choice2: 2
and each choice3: 1
.
Any advice on how to build a loop to get this result?
I think the best solution here is a loop with some recursion. I have increased the size of the model in the example to show it going with n levels. Check the output with your javascript console.
var choices = ['choice1', 'choice2', 'choice3'];
var items = [{
choice1: 'taste',
choice2: 'good',
choice3: 'green-lemon'
}, {
choice1: 'taste',
choice2: 'bad',
choice3: 'green-lemon'
},
{
choice1: 'taste',
choice2: 'ok',
choice3: 'green-lemon'
},
{
choice1: 'taste',
choice2: 'ok',
choice3: 'green-lemon'
}];
function IsLastLevel(levelIndex) {
return (levelIndex == choices.length - 1);
}
function HandleLevel(currentItem, currentLevel, nextChoiceIndex) {
var nextLevelName = currentItem[choices[nextChoiceIndex]];
if (typeof currentLevel[nextLevelName] === 'undefined') {
currentLevel[nextLevelName] = {};
}
if (IsLastLevel(nextChoiceIndex)) {
if (currentLevel[nextLevelName] > 0) {
currentLevel[nextLevelName]++;
} else {
currentLevel[nextLevelName] = 1;
}
} else {
var goOneDeeper = nextChoiceIndex + 1;
HandleLevel(currentItem, currentLevel[nextLevelName], goOneDeeper);
}
}
var output = {};
for(var itemIndex in items)
{
var item = items[itemIndex];
HandleLevel(item, output, 0);
}
console.log(output);
JsFiddle Demo
Brainwipe has already given a very clean answer, but I thought I would try my hand anyway. This solution works by recursively reducing the list of items, level by level, until it reaches the leaf nodes.
function choiceTree(items, choices) {
// Return empty object if there were no choices.
if (!choices.length) return {};
var choice = choices.shift();
// Construct the current level of the tree.
var level = items.reduce(function(node, item) {
var value = item[choice];
// Add item if branch node or set to 1 if leaf node.
node[value] = (choices.length)
? (node[value] || []).concat(item)
: 1;
return node;
}, {});
// Return if there are no remaining choices.
if (!choices.length) return level;
// Recursively construct the next level.
for (var node in level)
level[node] = choiceTree(level[node], choices.slice());
return level;
}
jsFiddle demo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With