我有一个复杂的json文件,我必须处理javascript使其分层,以便稍后构建树。 json的每个条目都有: Id:唯一的Id, parentId:父节点的id(如果节点是树的根,则为0) Level:树的深度级别

json数据已经“有序”。我的意思是,一个条目在它上面有一个父节点或兄弟节点,在它下面有一个子节点或兄弟节点。

输入:

{
    "People": [
        {
            "id": "12",
            "parentId": "0",
            "text": "Man",
            "level": "1",
            "children": null
        },
        {
            "id": "6",
            "parentId": "12",
            "text": "Boy",
            "level": "2",
            "children": null
        },
                {
            "id": "7",
            "parentId": "12",
            "text": "Other",
            "level": "2",
            "children": null
        },
        {
            "id": "9",
            "parentId": "0",
            "text": "Woman",
            "level": "1",
            "children": null
        },
        {
            "id": "11",
            "parentId": "9",
            "text": "Girl",
            "level": "2",
            "children": null
        }
    ],
    "Animals": [
        {
            "id": "5",
            "parentId": "0",
            "text": "Dog",
            "level": "1",
            "children": null
        },
        {
            "id": "8",
            "parentId": "5",
            "text": "Puppy",
            "level": "2",
            "children": null
        },
        {
            "id": "10",
            "parentId": "13",
            "text": "Cat",
            "level": "1",
            "children": null
        },
        {
            "id": "14",
            "parentId": "13",
            "text": "Kitten",
            "level": "2",
            "children": null
        },
    ]
}

预期产量:

{
    "People": [
        {
            "id": "12",
            "parentId": "0",
            "text": "Man",
            "level": "1",
            "children": [
                {
                    "id": "6",
                    "parentId": "12",
                    "text": "Boy",
                    "level": "2",
                    "children": null
                },
                {
                    "id": "7",
                    "parentId": "12",
                    "text": "Other",
                    "level": "2",
                    "children": null
                }   
            ]
        },
        {
            "id": "9",
            "parentId": "0",
            "text": "Woman",
            "level": "1",
            "children":
            {

                "id": "11",
                "parentId": "9",
                "text": "Girl",
                "level": "2",
                "children": null
            }
        }

    ],    

    "Animals": [
        {
            "id": "5",
            "parentId": "0",
            "text": "Dog",
            "level": "1",
            "children": 
                {
                    "id": "8",
                    "parentId": "5",
                    "text": "Puppy",
                    "level": "2",
                    "children": null
                }
        },
        {
            "id": "10",
            "parentId": "13",
            "text": "Cat",
            "level": "1",
            "children": 
            {
                "id": "14",
                "parentId": "13",
                "text": "Kitten",
                "level": "2",
                "children": null
            }
        }

    ]
}

当前回答

经过多次尝试,我得出了这个结论:

const arrayToTree = (arr, parent = 0) => arr .filter(item => item.parent === parent).map(child => ({ ...child, children: arrayToTree(arr, child.index) }));

   

const entries = [ { index: 1, parent: 0 }, { index: 2, parent: 1 }, { index: 3, parent: 2 }, { index: 4, parent: 2 }, { index: 5, parent: 4 }, { index: 6, parent: 5 }, { index: 7, parent: 6 }, { index: 8, parent: 7 }, { index: 9, parent: 8 }, { index: 10, parent: 9 }, { index: 11, parent: 7 }, { index: 13, parent: 11 }, { index: 12, parent: 0 } ]; const arrayToTree = (arr, parent = 0) => arr .filter(item => item.parent === parent) .map(child => ({ ...child, children: arrayToTree(arr, child.index) })); console.log(arrayToTree(entries));

其他回答

它可能是有用的包列表到树 安装:

bower install list-to-tree --save

or

npm install list-to-tree --save

例如,有列表:

var list = [
  {
    id: 1,
    parent: 0
  }, {
    id: 2,
    parent: 1
  }, {
    id: 3,
    parent: 1
  }, {
    id: 4,
    parent: 2
  }, {
    id: 5,
    parent: 2
  }, {
    id: 6,
    parent: 0
  }, {
    id: 7,
    parent: 0
  }, {
    id: 8,
    parent: 7
  }, {
    id: 9,
    parent: 8
  }, {
    id: 10,
    parent: 0
  }
];

使用包列表到树:

var ltt = new LTT(list, {
  key_id: 'id',
  key_parent: 'parent'
});
var tree = ltt.GetTree();

结果:

[{
  "id": 1,
  "parent": 0,
  "child": [
    {
      "id": 2,
      "parent": 1,
      "child": [
        {
          "id": 4,
          "parent": 2
        }, {
          "id": 5, "parent": 2
        }
      ]
    },
    {
      "id": 3,
      "parent": 1
    }
  ]
}, {
  "id": 6,
  "parent": 0
}, {
  "id": 7,
  "parent": 0,
  "child": [
    {
      "id": 8,
      "parent": 7,
      "child": [
        {
          "id": 9,
          "parent": 8
        }
      ]
    }
  ]
}, {
  "id": 10,
  "parent": 0
}];

ES6地图版本:

getTreeData = (items) => {
  if (items && items.length > 0) {
    const data = [];
    const map = {};
    items.map((item) => {
      const id = item.id; // custom id selector !!!
      if (!map.hasOwnProperty(id)) {
        // in case of duplicates
        map[id] = {
          ...item,
          children: [],
        };
      }
    });
    for (const id in map) {
      if (map.hasOwnProperty(id)) {
        let mappedElem = [];
        mappedElem = map[id];
        /// parentId : use custom id selector for parent
        if (
          mappedElem.parentId &&
          typeof map[mappedElem.parentId] !== "undefined"
        ) {
          map[mappedElem.parentId].children.push(mappedElem);
        } else {
          data.push(mappedElem);
        }
      }
    }
    return data;
  }
  return [];
};

/// use like this :

const treeData = getTreeData(flatList);

有同样的问题,但我不能确定数据是否已排序。我不能使用第三方库,所以这只是香草Js;输入数据可以从@Stephen的例子中获取;

var arr = [ {'id':1 ,'parentid' : 0}, {'id':4 ,'parentid' : 2}, {'id':3 ,'parentid' : 1}, {'id':5 ,'parentid' : 0}, {'id':6 ,'parentid' : 0}, {'id':2 ,'parentid' : 1}, {'id':7 ,'parentid' : 4}, {'id':8 ,'parentid' : 1} ]; function unflatten(arr) { var tree = [], mappedArr = {}, arrElem, mappedElem; // First map the nodes of the array to an object -> create a hash table. for(var i = 0, len = arr.length; i < len; i++) { arrElem = arr[i]; mappedArr[arrElem.id] = arrElem; mappedArr[arrElem.id]['children'] = []; } for (var id in mappedArr) { if (mappedArr.hasOwnProperty(id)) { mappedElem = mappedArr[id]; // If the element is not at the root level, add it to its parent array of children. if (mappedElem.parentid) { mappedArr[mappedElem['parentid']]['children'].push(mappedElem); } // If the element is at the root level, add it to first level elements array. else { tree.push(mappedElem); } } } return tree; } var tree = unflatten(arr); document.body.innerHTML = "<pre>" + (JSON.stringify(tree, null, " "))

JS小提琴

平面阵列到树

我已经编写了一个测试脚本来评估用户shekhardtu(见答案)和FurkanO(见答案)提出的两种最通用的解决方案的性能(意味着输入不需要事先排序,代码不依赖于第三方库)。

http://playcode.io/316025?tabs=console&script.js&output

FurkanO的解决方案似乎是最快的。

/* ** performance test for https://stackoverflow.com/questions/18017869/build-tree-array-from-flat-array-in-javascript */ // Data Set (e.g. nested comments) var comments = [{ id: 1, parent_id: null }, { id: 2, parent_id: 1 }, { id: 3, parent_id: 4 }, { id: 4, parent_id: null }, { id: 5, parent_id: 4 }]; // add some random entries let maxParentId = 10000; for (let i=6; i<=maxParentId; i++) { let randVal = Math.floor((Math.random() * maxParentId) + 1); comments.push({ id: i, parent_id: (randVal % 200 === 0 ? null : randVal) }); } // solution from user "shekhardtu" (https://stackoverflow.com/a/55241491/5135171) const nest = (items, id = null, link = 'parent_id') => items .filter(item => item[link] === id) .map(item => ({ ...item, children: nest(items, item.id) })); ; // solution from user "FurkanO" (https://stackoverflow.com/a/40732240/5135171) const createDataTree = dataset => { let hashTable = Object.create(null) dataset.forEach( aData => hashTable[aData.id] = { ...aData, children : [] } ) let dataTree = [] dataset.forEach( aData => { if( aData.parent_id ) hashTable[aData.parent_id].children.push(hashTable[aData.id]) else dataTree.push(hashTable[aData.id]) } ) return dataTree }; /* ** lets evaluate the timing for both methods */ let t0 = performance.now(); let createDataTreeResult = createDataTree(comments); let t1 = performance.now(); console.log("Call to createDataTree took " + Math.floor(t1 - t0) + " milliseconds."); t0 = performance.now(); let nestResult = nest(comments); t1 = performance.now(); console.log("Call to nest took " + Math.floor(t1 - t0) + " milliseconds."); //console.log(nestResult); //console.log(createDataTreeResult); // bad, but simple way of comparing object equality console.log(JSON.stringify(nestResult)===JSON.stringify(createDataTreeResult));

一个更简单的从列表到树的函数

NPM安装列表到树精简版

listToTree(列表)

来源:

function listToTree(data, options) {
    options = options || {};
    var ID_KEY = options.idKey || 'id';
    var PARENT_KEY = options.parentKey || 'parent';
    var CHILDREN_KEY = options.childrenKey || 'children';

    var tree = [],
        childrenOf = {};
    var item, id, parentId;

    for (var i = 0, length = data.length; i < length; i++) {
        item = data[i];
        id = item[ID_KEY];
        parentId = item[PARENT_KEY] || 0;
        // every item may have children
        childrenOf[id] = childrenOf[id] || [];
        // init its children
        item[CHILDREN_KEY] = childrenOf[id];
        if (parentId != 0) {
            // init its parent's children object
            childrenOf[parentId] = childrenOf[parentId] || [];
            // push it into its parent's children object
            childrenOf[parentId].push(item);
        } else {
            tree.push(item);
        }
    };

    return tree;
}

斯菲德尔