【问题标题】:Reorder a JS object in a child-parent structure在子父结构中重新排序 JS 对象
【发布时间】:2013-10-07 10:11:56
【问题描述】:

我正面临着一个脑筋急转弯(至少对我来说): 我得到一个 json 文件,其中包含一个深度的数据对象数组,如下所示:

[
{"id":1, "name":"Sport", "parent_id":0, "children":[]},
{"id":2, "name":"Tennis", "parent_id":4, "children":[]},
{"id":3, "name":"Climbing", "parent_id":5, "children":[]},
{"id":4, "name":"Indoor", "parent_id":1, "children":[]},
{"id":5, "name":"Outdoor", "parent_id":1, "children":[]},
{"id":6, "name":"Bowling", "parent_id":4, "children":[]}
]

我怎样才能将它转换成一个树结构,将孩子放在他们父母的孩子数组中?对象并不总是按正确的顺序排列,一个孩子在数组中可以排在它的父母之前。 (如我的示例中的 id 2 和 3)

这就是我最终需要的方式:

[
{"id":1, "name":"Sport", "parent_id":0, "children":
  [
    {"id":4, "name":"Indoor", "parent_id":1, "children":
    [
      {"id":2, "name":"Tennis", "parent_id":4, "children":[]},
      {"id":6, "name":"Bowling", "parent_id":4, "children":[]},
    ]},
    {"id":5, "name":"Outdoor", "parent_id":1, "children":
    [
      {"id":3, "name":"Climbing", "parent_id":5, "children":[]}
    ]},
  ]}
]

知道如何实现吗?

我尝试遍历元素并将其父子数组内部推入,但是当父元素被移动时,下一个兄弟元素再也找不到父元素了...

【问题讨论】:

    标签: javascript jquery arrays json


    【解决方案1】:

    我不确定为什么每个人都如此热衷于编写低效的 O2 算法(嵌套的 for 循环),但这里有一个 O(n log n) 时间:

    function treeify(nodes) {
        var indexed_nodes = {}, tree_roots = [];
        for (var i = 0; i < nodes.length; i += 1) {
            indexed_nodes[nodes[i].id] = nodes[i];
        }
        for (var i = 0; i < nodes.length; i += 1) {
            var parent_id = nodes[i].parent_id;
            if (parent_id === 0) {
                tree_roots.push(nodes[i]);
            } else {
                indexed_nodes[parent_id].children.push(nodes[i]);
            }
        }
        return tree_roots;
    }
    
    var nodes = [
        {"id":1, "name":"Sport", "parent_id":0, "children":[]},
        {"id":2, "name":"Tennis", "parent_id":4, "children":[]},
        {"id":3, "name":"Climbing", "parent_id":5, "children":[]},
        {"id":4, "name":"Indoor", "parent_id":1, "children":[]},
        {"id":5, "name":"Outdoor", "parent_id":1, "children":[]},
        {"id":6, "name":"Bowling", "parent_id":4, "children":[]}
    ];
    
    console.log(JSON.stringify(treeify(nodes), undefined, "\t"));
    

    【讨论】:

      【解决方案2】:

      应该这样做http://jsfiddle.net/arPgr/

      var arr = [
      {"id":1, "name":"Sport", "parent_id":0, "children":[]},
      {"id":2, "name":"Tennis", "parent_id":4, "children":[]},
      {"id":3, "name":"Climbing", "parent_id":5, "children":[]},
      {"id":4, "name":"Indoor", "parent_id":1, "children":[]},
      {"id":5, "name":"Outdoor", "parent_id":1, "children":[]},
      {"id":6, "name":"Bowling", "parent_id":4, "children":[]}
      ]
      
      var i = 0, len = arr.length, item, parent, id, key, treeArr = {};
      
      for (; i < len; i++) {
          item = arr[i];
          parent = item.parent_id;
          id = item.id;
      
          if (treeArr[id] == undefined) {
             treeArr[id] = item;   
          } else if (typeof treeArr[id] == 'object') {
              for (key in item) {
                  if (key == 'children') continue;
                  treeArr[id][key] = item[key];   
              }        
          }
      
          if (typeof treeArr[parent] != 'object') {
              treeArr[parent] = { children: [] };   
          }
      
          treeArr[parent].children.push(treeArr[id]);
      }
      
      console.log(treeArr[0]);
      

      【讨论】:

        【解决方案3】:

        函数 reorder 会将您的数组转换为层次结构。它返回具有 parent_id ===0 的对象作为根对象。 see this fiddle

        var src = 
            [
        {"id":1, "name":"Sport", "parent_id":0, "children":[]},
        {"id":2, "name":"Tennis", "parent_id":4, "children":[]},
        {"id":3, "name":"Climbing", "parent_id":5, "children":[]},
        {"id":4, "name":"Indoor", "parent_id":1, "children":[]},
        {"id":5, "name":"Outdoor", "parent_id":1, "children":[]},
        {"id":6, "name":"Bowling", "parent_id":4, "children":[]}
        ];
        
        function reorder(orig)
        {
            var cnt,id, pid, root, fcnt;
            for(cnt = 0; cnt < orig.length; cnt = cnt + 1) {
                pid = orig[cnt].parent_id;
                id = orig[cnt].id;
                if (pid === 0) {
                    root = orig[cnt]
                }
                // loop until cnt, then skip that index
                for (fcnt=0;fcnt<cnt;fcnt=fcnt+1){
                    if (orig[fcnt].parent_id === id) {
                        orig[cnt].children.push(orig[fcnt]);
                    }
                }
                // loop from cnt + 1 till end of array 
                for (fcnt=cnt+1;fcnt<orig.length;fcnt=fcnt+1){
                   if (orig[fcnt].parent_id === id) {
                        orig[cnt].children.push(orig[fcnt]);
                    }
                }            
            }
            return root;
        }
        
        var dest = reorder(src);
        console.log(JSON.stringify(dest));
        

        【讨论】:

          【解决方案4】:

          试试这个

          for (var i = 0; i < a.length; i++) {
              for (var j = 0; j < a.length; j++) {
                  if(a[j].id == a[i].parent_id){
                      a[i].children.push(a[j])
                  }
              }
          }
          

          Fiddle

          【讨论】:

          • 小bug,需要这样做:if(a[j].id == a[i].parent_id){
          • 尽管如此,所有基本数组元素仍然存在。
          【解决方案5】:

          使用一个新的数组来存储结果..

          var ret = [];
          for (var i = 0; i < arr.length; i++) {
              if (arr[i].parent_id == 0) {
                  ret.push(arr[i]);
                  continue;
              }
              for (var j = 0; j < arr.length; j++) {
                  if (arr[i].parent_id == arr[j].id) {
                      arr[j].children.push(arr[i]);
                      break;
                  }
              }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-02-29
            • 1970-01-01
            • 1970-01-01
            • 2023-01-14
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多