Javascript将对象数组转换为树 [英] Javascript convert array of objects to tree

查看:118
本文介绍了Javascript将对象数组转换为树的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试转换此结构:

I am trying to convert this structure:

var initial = [ 
{ Phase: "Phase 1", Step: "Step 1", Task: "Task 1", Value: "5" },
{ Phase: "Phase 1", Step: "Step 1", Task: "Task 2", Value: "10" },
{ Phase: "Phase 1", Step: "Step 2", Task: "Task 1", Value: "15" },
{ Phase: "Phase 1", Step: "Step 2", Task: "Task 2", Value: "20" },
{ Phase: "Phase 2", Step: "Step 1", Task: "Task 1", Value: "25" },
{ Phase: "Phase 2", Step: "Step 1", Task: "Task 2", Value: "30" },
{ Phase: "Phase 2", Step: "Step 2", Task: "Task 1", Value: "35" },
{ Phase: "Phase 2", Step: "Step 2", Task: "Task 2", Value: "40" }
];

对此:

var example = {
"Phase 1": {
    "Step 1": {
        "Task 1": { Phase: "Phase 1", Step: "Step 1", Task: "Task 1", Value: "5" }, 
        "Task 2": { Phase: "Phase 1", Step: "Step 1", Task: "Task 2", Value: "10" }
    } ,
    "Step 2": {
        "Task 1": { Phase: "Phase 1", Step: "Step 2", Task: "Task 1", Value: "15" }, 
        "Task 2": { Phase: "Phase 1", Step: "Step 2", Task: "Task 2", Value: "20" }
    }
} ,
"Phase 2": {        
    "Step 1": {
        "Task 1": { Phase: "Phase 2", Step: "Step 1", Task: "Task 1", Value: "25" }, 
        "Task 2": { Phase: "Phase 2", Step: "Step 1", Task: "Task 2", Value: "30" },
    } ,
    "Step 2": {
        "Task 1": { Phase: "Phase 2", Step: "Step 2", Task: "Task 1", Value: "35" }, 
        "Task 2": { Phase: "Phase 2", Step: "Step 2", Task: "Task 2", Value: "40" }     
    }
}
};

所以我可以轻松提取出这样的值example['Phase 2']['Step 1']['Task 1']['Value']

so I can easily extract a value like this example['Phase 2']['Step 1']['Task 1']['Value']

我已经使用groupBy这样的函数完成了第一步:

I have done the first step using a groupBy function like this one:

function groupBy(d, arr) {
return arr.reduce(function(acc, i) {
    var p = i[d];
    var temp = acc[p] || [];
    temp.push(i);
    acc[p] = temp;
    return acc;
}, {})
}

所以当我做var groupedByPhase = groupBy('Phase', initial); 我得到groupedByPhase:

{
"Phase 1" : [
{ Phase: "Phase 1", Step: "Step 1", Task: "Task 1", Value: "5" },
{ Phase: "Phase 1", Step: "Step 1", Task: "Task 2", Value: "10" },
{ Phase: "Phase 1", Step: "Step 2", Task: "Task 1", Value: "15" },
{ Phase: "Phase 1", Step: "Step 2", Task: "Task 2", Value: "20" },
],
"Phase 2": [
{ Phase: "Phase 2", Step: "Step 1", Task: "Task 1", Value: "25" },
{ Phase: "Phase 2", Step: "Step 1", Task: "Task 2", Value: "30" },
{ Phase: "Phase 2", Step: "Step 2", Task: "Task 1", Value: "35" },
{ Phase: "Phase 2", Step: "Step 2", Task: "Task 2", Value: "40" }
] 
}

我还可以使用此功能按步骤分组:

I also manage to group by Step using this function:

function groupByInNestedObj(item, obj) {
var x = {};
for (var i in obj) {
    x[i] = groupBy(item, obj[i]);
}
return x;
}

可以在调用groupByInNestedObj('Step', groupBy('Phase', initial))

 {
"Phase 1" : {
    "Step 1": [
    { Phase: "Phase 1", Step: "Step 1", Task: "Task 1", Value: "5" },
    { Phase: "Phase 1", Step: "Step 1", Task: "Task 2", Value: "10" }],
    "Step 2": [
    { Phase: "Phase 1", Step: "Step 2", Task: "Task 1", Value: "15" },
    { Phase: "Phase 1", Step: "Step 2", Task: "Task 2", Value: "20" },
    ]},
"Phase 2": {
    "Step 1:" [
    { Phase: "Phase 2", Step: "Step 1", Task: "Task 1", Value: "25" },
    { Phase: "Phase 2", Step: "Step 1", Task: "Task 2", Value: "30" }],
    "Step 2:"[
    { Phase: "Phase 2", Step: "Step 2", Task: "Task 1", Value: "35" },
    { Phase: "Phase 2", Step: "Step 2", Task: "Task 2", Value: "40" }
    ]}
}

但是我有点卡在这里,要做下一个. 理想情况下,我希望能够执行groupBy("Task", groupBy("Step", groupBy("Phase", initial))),以便groupBy在树的最深层进行分组. 欢迎任何建议!

However I am a bit stuck here, to do the next one. Ideally I would like to be able to do groupBy("Task", groupBy("Step", groupBy("Phase", initial))) so that groupBy groups at the deepest level of the tree. Any suggestion welcome!

注意:我确实尝试了第二步来实现此功能

Note: I did try for the 2nd step to implement this function

function groupByInNestedObj2 (item, obj) {
    var x = {};
    for(var i in obj) {
        for (var j in obj[i]) {
            x[i][j] = groupBy(item, obj[i][j]);
        }
    }
    return x;
}

但它似乎不起作用.

注释2:上一个函数的第二个版本有效,但是它不是纯的,因为它修改了通过它的对象

Note 2: The second version of the previous function works but is not pure as it modifies the object passed through it

function groupByInNestedObj2 (item, obj) {
    var x = {};
    for(var i in obj) {
        x[i] = obj[i]
        for (var j in x[i]) {
            x[i][j] = groupBy('Task', x[i][j]);
        }
    }
    return x;
}

因此,当我执行var groupByPhaseAndStepAndTask = groupByInNestedObj2('Task', groupByPhaseAndStep)时,groupByPhaseAndStep也被修改,这是不希望的副作用.仍在努力.

so when I do var groupByPhaseAndStepAndTask = groupByInNestedObj2('Task', groupByPhaseAndStep) groupByPhaseAndStep is modified too, which is an undesirable side effect. Still working on it.

推荐答案

使用lodash和 answer :

A more generic way using lodash and this answer:

var initial = [
  { Phase: "Phase 1", Step: "Step 1", Task: "Task 1", Value: "5" },
  { Phase: "Phase 1", Step: "Step 1", Task: "Task 2", Value: "10" },
  { Phase: "Phase 1", Step: "Step 2", Task: "Task 1", Value: "15" },
  { Phase: "Phase 1", Step: "Step 2", Task: "Task 2", Value: "20" },
  { Phase: "Phase 2", Step: "Step 1", Task: "Task 1", Value: "25" },
  { Phase: "Phase 2", Step: "Step 1", Task: "Task 2", Value: "30" },
  { Phase: "Phase 2", Step: "Step 2", Task: "Task 1", Value: "35" },
  { Phase: "Phase 2", Step: "Step 2", Task: "Task 2", Value: "40" }
];

_.mixin({
  groupByMulti: function(obj, values, context) {
    if (!values.length) return obj;
    var byFirst = _.groupBy(obj, _.head(values), context);
    for (var prop in byFirst) {
      byFirst[prop] = _.groupByMulti(byFirst[prop], _.tail(values), context);
    }
    return byFirst;
  }
});

var tree = _(initial).groupByMulti(['Phase', 'Step', 'Task']);
$('#pre').append(JSON.stringify(tree, null, 3));

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.0.0/lodash.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<pre id='pre'></pre>

这篇关于Javascript将对象数组转换为树的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆