如何循环通过对象并创建树对象

How to loop through Object and create a tree Object

本文关键字:对象 创建 何循环 循环      更新时间:2023-11-11

我有一个平面对象和一个数组,我需要从中构建一个树状对象。

choices: ['choice1', 'choice2', 'choice3'];
items: [
    {
        choice1: 'taste',
        choice2: 'good',
        choice3: 'green-lemon'
    },
    {
        choice1: 'taste',
        choice2: 'bad',
        choice3: 'green-lemon'
    }
];

数组描述了树中每个选项的级别。我不知道以后会有多少选择、项目或级别。

如何获得以下对象:

output: {
    taste: {
        good: {
            green-lemon:1
        },
        bad: {
            green-lemon:1
        }
    }
}

我需要得到一个对象来描述每个级别上有多少项。在该示例中,这是choice1: 1; choice2: 2和每个choice3: 1

关于如何构建一个循环来获得这个结果,有什么建议吗?

我认为这里最好的解决方案是使用一些递归的循环。我在示例中增加了模型的大小,以显示它具有n个级别。使用javascript控制台检查输出。

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演示

Brainwipe已经给出了一个非常明确的答案,但我想我无论如何都会尝试一下。该解决方案通过递归地逐级减少项目列表,直到到达叶节点。

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演示