【问题标题】:Flattening hierarchical json data for table display扁平化分层 json 数据以进行表格显示
【发布时间】:2019-01-05 19:40:42
【问题描述】:

这是树的基本结构:

{ 
    "DescId" : "1", 
    "Desc" : "Parent 1", 
    "ParentId" : "null", 
    "Order" : 1.0, 
    "Type" : "A", 
    "Parent" : null, 
    "Depth" : 0.0
}
{ 
    "DescId" : "1.1", 
    "Desc" : "Child 1", 
    "ParentId" : "1", 
    "Order" : 1.0, 
    "Type" : "B", 
    "Parent" : "Parent 1", 
    "Depth" : 1.0
}
{ 
    "DescId" : "1.2", 
    "Desc" : "Child 2", 
    "ParentId" : "1", 
    "Order" : 2.0, 
    "Type" : "B", 
    "Parent" : "Parent 1", 
    "Depth" : 1.0
}
{ 
    "DescId" : "1.1.1", 
    "Desc" : "Grand Child 1", 
    "ParentId" : "1.1", 
    "Order" : 1.0, 
    "Type" : "C", 
    "Parent" : "Child 1", 
    "Depth" : 2.0
}
{ 

    "DescId" : "1.1.1.1", 
    "Desc" : "Great Grand Child 1", 
    "ParentId" : "1.1.1", 
    "Order" : 1.0, 
    "Type" : "D", 
    "Parent" : "Grand Child 1", 
    "Depth" : 3.0
}
{ 

    "DescId" : "2", 
    "Desc" : "Parent 2", 
    "ParentId" : null, 
    "Order" : 2.0, 
    "Type" : "A", 
    "Parent" : null, 
    "Depth" : 0.0
}

我有这个分层的 json 数据如下:

[
  {
    "DescId": "1",
    "Desc": "Parent 1",
    "Type": "A",
    "children": [
      {
        "DescId": "1.2",
        "Desc": "Child 2",
        "ParentId": "1",
        "Order": 2,
        "Type": "B",
        "Parent": "Parent 1",
        "Depth": 1
      },
      {
        "DescId": "1.1",
        "Desc": "Child 1",
        "ParentId": "1",
        "Order": 1,
        "Type": "B",
        "Parent": "Parent 1",
        "Depth": 1
      }
    ]
  },
  {
    "DescId": "1.1",
    "Desc": "Child 1",
    "Type": "B",
    "children": [
      {
        "DescId": "1.1.1",
        "Desc": "Grand Child 1",
        "ParentId": "1.1",
        "Order": 1,
        "Type": "C",
        "Parent": "Child 1",
        "Depth": 2
      }
    ]
  },
  {
    "DescId": "1.2",
    "Desc": "Child 2",
    "Type": "B",
    "children": []
  },
  {
    "DescId": "1.1.1",
    "Desc": "Grand Child 1",
    "Type": "Consequence",
    "children": [
      {
        "DescId": "1.1.1.1",
        "Desc": "Great Grand Child 1",
        "ParentId": "1.1.1",
        "Order": 1.0,
        "Type": "D",
        "Parent": "Grand Child 1",
        "Depth": 3.0
      }
    ]
  },
  {
    "DescId": "1.1.1.1",
    "Desc": "Great Grand Child 1",
    "Type": "D",
    "children": []
  },
  {
    "DescId": "2",
    "Desc": "Parent 2",
    "Type": "A",
    "children": []
  }
]

我有这个要求,我需要将此分层树显示为表格结构。

所以数据需要如下:

[
  {
    "A" + "DescId" : "1",
    "A" + "Desc" : "Parent",
    "B" + "DescId" : "1.1",
    "B" + "Desc" : "Child 1,
    "C" + "DescId" : "1.1.1",
    "C" + "Desc" : "Grand Child 1"
    "D" + "DescId" : "1.1.1.1",
    "D" + "Desc" : "Great Grand child 1"
  },
  {
    "A" + "DescId" : "1",
    "A" + "Desc" : "Parent 1",
    "B" + "DescId" : "1.2"
    "B" + "Desc" : "Child 2
    //if there are any further generations like 1.2.1 or 1.2.1.1 should be present here
  },
  {
    "A" + "DescId" : "2",
    "A" + "Desc" : "Parent 2"
  }
]

我已经在 javascript 和 lodash 中尝试过以下代码:

function reformatData(sentData) {
        var finalData = {};
        var returnArray = [];
        if (sentData.length > 0) {
            var propertyNameArray = Object.keys(sentData[0]);

            for (var i = 0; i < sentData.length; i++) {
                var type = sentData[i].Type;
                finalData[type + propertyNameArray[0]] = sentData[i].DescId;
                finalData[type + propertyNameArray[1]] = sentData[i].Desc;
                if (sentData[i].children && sentData[i].children.length > 0) {
                    var children = _.orderBy(sentData[i].children, ['Order'], ['asc']);
                    reformatData(children);
                }
            }
        }
        returnArray.push(finalData);
        return returnArray;
    }

上面的代码忽略了第一个父级,只添加了下一个可用的父级。谁能帮我指出我在这里缺少的东西。以下是正在生成的输出代码:

[
  {
    "ADescid":"2",
    "ADesc":"Parent 2",
    "BDescid":"1.2",
    "BDesc":"Child 2",
    "CDescid":"1.1.1",
    "CDesc":"Grand Child 1",
    "DDescid":"1.1.1.1",
    "DDesc":"Great grand child 1"
  }
]

【问题讨论】:

  • 所以你想得到树的每条路径,对吧?
  • 是的,作为数组的不同对象。

标签: javascript arrays json mongodb lodash


【解决方案1】:

此提案分三个步骤进行:

  1. 构建树。
  2. 收集所有节点到最后的叶子。
  3. 使用想要的键生成单个对象作为最终结果。

function getTree(array, root) {
    var o = {};
    array.forEach(function (a) {
        o[a.DescId] = Object.assign({}, a, o[a.DescId]);
        o[a.ParentId] = o[a.ParentId] || {};
        o[a.ParentId].children = o[a.ParentId].children || [];
        o[a.ParentId].children.push(o[a.DescId]);
    });
    return o[root].children;
}

function getLeafes(tree) {
    var result = [];
    tree.forEach(function iter(temp) {
        return function ({ DescId, Desc, Type, children }) {
            var t = temp.concat({ DescId, Desc, Type });
            if (!children) {
                result.push(t);
                return;
            }
            children.forEach(iter(t));
        };
    }([]));
    return result;
}

var nodes = [{ DescId: "1", Desc: "Parent 1", ParentId: "null", Order: 1, Type: "A", Parent: null, Depth: 0 }, { DescId: "1.1", Desc: "Child 1", ParentId: "1", Order: 1, Type: "B", Parent: "Parent 1", Depth: 1 }, { DescId: "1.2", Desc: "Child 2", ParentId: "1", Order: 2, Type: "B", Parent: "Parent 1", Depth: 1 }, { DescId: "1.1.1", Desc: "Grand Child 1", ParentId: "1.1", Order: 1, Type: "C", Parent: "Child 1", Depth: 2 }, { DescId: "1.1.1.1", Desc: "Great Grand Child 1", ParentId: "1.1.1", Order: 1, Type: "D", Parent: "Grand Child 1", Depth: 3 }, { DescId: "2", Desc: "Parent 2", ParentId: null, Order: 2, Type: "A", Parent: null, Depth: 0 }],
    tree = getTree(nodes, null),
    leaves = getLeafes(tree),
    result = leaves.map(a => a.reduce((o, { DescId, Desc, Type }) => Object.assign(o, { [Type + 'DescId']: DescId, [Type + 'Desc']: Desc }), {}));

console.log(tree);
console.log(leaves);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

    【解决方案2】:

    这可以通过递归生成器函数以非常优雅的方式解决:

     function* paths(node, parent = {}) {
       const current = {
         ...parent,
         [node.type + "DescId"]: node.DescId,
         [node.type + "Desc"]: node.Desc,
       };
    
       if(node.children && node.children.length) {
         for(const child of node.children)
            yield* paths(child, current);
       } else {
         yield current;
       }
    }
    
    // The following is only needed as your root is an array not a node
    function* pathArray(array) {
      for(const el of array) yield* paths(el);
    }
    

    所以你可以这样称呼它:

    const result = [...pathArray(yourTreeArray)];
    

    【讨论】:

    • @vani 是的,我必须解决一些问题,检查编辑:)
    • @Jonas.W:这只会生成到第一个孩子,我需要像这样{ "ADescId: "1", "ADesc" : "Parent 1", "BDescId" : "1.1", "BDesc" : "Child 1", "CDescId" : 1.1.1", "CDesc" : "Grand Child", "DDescId" : "1.1.1.1", "DDesc" : Great Grand Child 1"}, {"ADescId" : "1", "ADesc": Parent 1, "BDescId" : 1.2", "BDesc": "Child 2", "CDescId" : "1.2.1", "CDesc": Grand Child of Parent 1"}
    • @vani 你的树只有两个深度?那怎么可能有两个以上的节点合二为一呢?
    • @Jonas.W :我用我的基本树结构更新了问题。
    • @vani 我还是不太明白。而且我在接下来的 24 小时内处于离线状态...也许其他人了解您的问题并能够回答
    猜你喜欢
    • 1970-01-01
    • 2019-03-15
    • 2022-09-23
    • 2021-02-03
    • 2019-06-22
    • 2016-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多