Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何循环对象并创建树对象_Javascript_Loops_Object - Fatal编程技术网

Javascript 如何循环对象并创建树对象

Javascript 如何循环对象并创建树对象,javascript,loops,object,Javascript,Loops,Object,我有一个平面对象和一个数组,我需要从中构造一个树状对象 choices: ['choice1', 'choice2', 'choice3']; items: [ { choice1: 'taste', choice2: 'good', choice3: 'green-lemon' }, { choice1: 'taste', choice2: 'bad', choice3: '

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

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
        }
    }
}
我需要得到一个对象,描述每个级别上有多少项。在本例中,这是
选项1:1
选择2:2
和每个
选择3: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);

Brainwipe已经给出了一个非常清晰的答案,但我想我还是会试试我的手。该解决方案的工作原理是递归地逐级减少项目列表,直到它到达叶节点

功能选项树(项目、选项){
//如果没有选择,则返回空对象。
if(!choices.length)返回{};
var choice=choices.shift();
//构建树的当前级别。
var级别=items.reduce(函数(节点,项){
var值=项目[选择];
//如果是分支节点,则添加项;如果是叶节点,则设置为1。
节点[值]=(选项.长度)
?(节点[值]| |[]).concat(项目)
: 1;
返回节点;
}, {});
//如果没有剩余的选项,则返回。
如果(!choices.length)返回级别;
//递归地构造下一层。
for(级别中的变量节点)
level[node]=choiceTree(level[node],choices.slice());
回报水平;
}

还会有更多的级别吗?这个数据集会扩展吗?
choices
数组是用来描述树中每个选项的级别的吗@brainwipe的问题也与正确的解决方案有关。@brainwipe:可能只有2个级别的选择,可能有5个级别的选择。“选项”数组和“项目”对象在运行时不会更改。@JordanGray:items包含更多数据。选项数组将树描述为level0是第一项,level0是最后一项。@这很有用。你想作为数组的结果显示树、物品计数还是两者都显示?也非常感谢。代码要少得多,但更难阅读。我还没有使用reduce,但肯定会看看它。谢谢。
Array.reduce
真的很酷而且没有得到充分利用,你一定要好好读一读!)它所做的只是将数组“缩减”为单个值;你可以,但我认为额外的代码更混乱。IE 8及以下版本不支持它,但它是。