【问题标题】:How to convert flat multi-branch data to hierarchical JSON?如何将平面多分支数据转换为分层 JSON?
【发布时间】:2016-06-14 08:03:30
【问题描述】:
[
  {
    "id": "a",
    "pid": "a",
    "name": "AA",
  },
  {
    "id": "b",
    "pid": "a",
    "name": "BB",
  },
  {
    "id": "c",
    "pid": "a",
    "name": "CC",
  },
  {
    "id": "x",
    "pid": "b",
    "name": "XX",
  }
]

以上是我从数据库中得到的数据。每个人都有一个id 和一个pidpid 指向该人的更高级别人员的id。如果一个人的等级最高,则id 等于pid

我想将原始数据转换为分层 JSON,如下所示:

[
  {
    "id": "a",
    "name": "AA",
    "child": [
      {
        "id": "b",
        "name": "BB"
        "child": [
          {
            "id": "x",
            "name": "XX"
          }
        ]
      },
      {
        "id": "c",
        "name": "CC"
      }
    ]  
  }
]

我正在使用 Node.js。

【问题讨论】:

  • 数据是按id排序的,还是随机排序的?
  • @NinaScholz 是随机排序的,但 ID 是唯一的。
  • 你怎么知道树的根?请添加更多数据以供检查。
  • @NinaScholz 当id 等于pid 时,他就是根。
  • 我更新了问题,谢谢!@NinaScholz

标签: javascript node.js algorithm tree


【解决方案1】:

我建议你创建一个树并将id === pid 作为树的根,它适用于未排序的数据。

它是如何工作的:

基本上,对于数组中的每个对象,它都将id 用于构建一个新对象,就像parentid 用于一个新对象。

例如:

{ "id": 6, "pid": 4 }

它首先用id生成这个属性:

"6": {
    "id": 6,
    "pid": 4
}

然后是pid:

"4": {
    "children": [
        {
            "id": 6,
            "pid": 4
        }
    ]
},

虽然所有对象都经过类似处理,但我们最终得到了一棵树。

如果id === pid,则找到根节点。这是后面返回的对象。

var data = [
        { "id": "f", "pid": "b", "name": "F" },
        { "id": "e", "pid": "c", "name": "E" },
        { "id": "d", "pid": "c", "name": "D" },
        { "id": "c", "pid": "b", "name": "C" },
        { "id": "a", "pid": "a", "name": "A" },
        { "id": "b", "pid": "a", "name": "B" }
    ],
    tree = function (data) {
        var r, o = Object.create(null);
        data.forEach(function (a) {
            a.children = o[a.id] && o[a.id].children;
            o[a.id] = a;
            if (a.id === a.pid) {
                r = a;
            } else {
                o[a.pid] = o[a.pid] || {};
                o[a.pid].children = o[a.pid].children || [];
                o[a.pid].children.push(a);
            }
        });
        return r;
    }(data);

console.log(tree);

【讨论】:

  • 谢谢!我现在知道如何解决这种问题了!
  • 值得一提的是,这个出色的算法充分利用了 JS 中对象作为引用类型的优势。这一事实简单地节省了大量的排序工作。
  • @AlexeiLevenkov,引用是我的一部分,它不是从其他地方复制的。
  • @NinaScholz 好的,只是想检查编辑是否合理。 (我不会对给定帖子独有的我自己的内容使用报价格式......但我认为没有任何强有力的指导反对它)。 (阅读时标记为“不再需要”)
【解决方案2】:

受Nina回答的影响,这是我的决定,仅作记录。

function corrugate(data){
  var root = "";
  return data.reduce((t,o) => {
    	                       o.id === o.pid && (root = o.id);
  	                           t[o.id]  ? t[o.id].name = o.name
  	                                    : t[o.id] = {id: o.id, name: o.name};
  	                           t[o.pid] ? o.pid !== o.id ? t[o.pid].children.push(t[o.id])
  	                                                     : t[o.pid].children = t[o.pid].children || []
  	                                    : t[o.pid] = {id: o.pid, children: [t[o.id]]};
  	                           return t;
                              },{})[root];
}

var   data = [{ "id": "f", "pid": "b", "name": "F" },
              { "id": "e", "pid": "c", "name": "E" },
              { "id": "b", "pid": "a", "name": "B" },
              { "id": "d", "pid": "c", "name": "D" },
              { "id": "c", "pid": "b", "name": "C" },
              { "id": "a", "pid": "a", "name": "A" }
             ];
console.log(corrugate(data));

【讨论】:

    猜你喜欢
    • 2022-11-19
    • 1970-01-01
    • 2019-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多