对于输入的扁平树:
let input = [{
levelId: '1'
}, {
levelId: '1.1'
}, {
levelId: '1.1.1'
}, {
levelId: '1.2'
}, {
levelId: '2'
}, {
levelId: '2.1.1'
}
]
将其转换为多级树的最佳方法是什么,其中levelId
定义树的级别:
let output = [{
levelId: '1',
children: [{
levelId: '1.1',
children: [{
levelId: '1.1.1'
}
]
}
]
}, {
levelId: '2',
children: [{
levelId: '2.1.1'
}
]
}
]
使用Lodash。
答案 0 :(得分:2)
我首先根据对象级别对数组进行排序,然后创建一个中间对象以将每个级别ID映射到对象本身,并从中间对象中找到其父对象。然后我输出一个没有父对象的数组。
希望获得帮助。
var input = [
{
levelId: '1'
},
{
levelId: '1.1'
},
{
levelId: '1.1.1'
},
{
levelId: '1.2'
},
{
levelId: '2'
},
{
levelId: '2.1.1'
},
{
levelId: '3.1'
},
{
levelId: '3.1.1'
}
];
function exec(input){
var temp = {};
//Sort the array by level then create an intermediate object that map level id with the level object and map with its parent
input.sort((a,b) => a.levelId.split(".").length - b.levelId.split(".").length).forEach( lvl => {
temp[lvl.levelId] = lvl;
if(lvl.levelId.indexOf('.') !== -1){
var parentLevelId = lvl.levelId;
var parent = undefined;
//Search parent level by level (ie. 3.1.1 -> 3.1 -> 3)
do{
if(parentLevelId.indexOf('.') === -1) break;
parentLevelId = parentLevelId.substr(0, parentLevelId.lastIndexOf("."));
parent = temp[parentLevelId];
}while(typeof parent === 'undefined')
if(typeof parent !== 'undefined'){
if(typeof parent.children === 'undefined'){
parent.children = [];
}
parent.children.push(lvl);
lvl.parent = parent;
}
}
});
//push the root object (level object that has no parent) to an output array
var output = [];
for(var key in temp){
if(typeof temp[key].parent !== 'undefined'){
delete temp[key]["parent"];
}else{
output.push(temp[key]);
}
}
return output;
}
console.log(JSON.stringify(exec(input), 0, 3));
答案 1 :(得分:0)
另一种方法:
代码:
let input = [{
levelId: '1'
}, {
levelId: '2.1.1'
}, {
levelId: '2.1.1.2.5'
}, {
levelId: '1.1'
}, {
levelId: '1.2'
}, {
levelId: '2'
}, {
levelId: '1.1.1.1.1'
}, {
levelId: '3.1.1.1.1'
}
]
console.log(JSON.stringify(treeify(input)))
function treeify(input) {
let built = {},
result = { levelId:"", children:[] };
// First pass: build the tree in the order you encounter the nodes:
buildTree();
// Second pass: look for children already having an ancestor
reorganize(result);
// For return value, start with list of top level nodes
return result.children
// --- First pass: build tree from flat list
function buildTree() {
for (let o of input) {
let parentId = getParentId(o.levelId);
addChild(built[parentId]||result,o);
built[o.levelId] = o;
}
}
// --- Second pass: switch parents if found
function reorganize(node) {
if (!("children" in node)) return;
// Backward loop, as items will be removed during the loop
for (let i=node.children.length-1;i>=0;i--) {
let c = node.children[i];
// Attach node to first ancestor found
for(let parentId = getParentId(c.levelId);parentId;parentId=getParentId(parentId)) {
if (parentId in built) {
if (built[parentId]==node) {
break; // Already in right position
}
addChild(built[parentId],c);
node.children.splice(i,1);
break;
}
}
}
// Do it recursively on all child nodes
node.children.forEach(reorganize);
}
// --- Insert a child
function addChild(parent,child) {
if (!("children" in parent)) {
parent.children = [];
}
parent.children.push(child);
}
// --- Determine parent id (by splitting off the last segment of the ID)
function getParentId(id) {
return id.replace(/^\d+$|\.\d+$/,"")
}
}