How to convert flat multi-branch data to hierarchi

2020-03-07 06:04发布

问题:

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

Above is the data I got from the database. Every person has an id and a pid, pid points to the person's higher level person's id. If a person has highest level, the id equals pid.

I want to convert the raw data to hierarchical JSON, like this:

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

I'm using Node.js.

回答1:

I suggest you to create a tree and take id === pid as a root for the tree, which works for unsorted data.

How it works:

Basically, for every object in the array, it takes the id for building a new object as parentid for a new object.

For example:

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

It generates this property first with id:

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

and then with pid:

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

and while all objects are similarly treated, we finally get a tree.

If id === pid, the root node is found. This is the object for the later return.

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);



回答2:

Influenced by the answer of Nina, this is my resolution just for the record.

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));