[英]Converting flat structure to hierarchical
我需要创建能够将平面对象转换为递归对象的函数。 这是我的示例:我有平面阵列:
var flatArray = [
{
Description: "G",
guid: "c8e63b35",
parent: null,
},
{
Description: "Z",
guid: "b1113b35",
parent: "c8e63b35",
},
{
Description: "F",
guid: "d2cc2233",
parent: "b1113b35",
},
{
Description: "L",
guid: "a24a3b1a",
parent: null,
},
{
Description: "K",
guid: "cd3b11caa",
parent: "a24a3b1a",
},
]
结果应该是:
recursiveArray = [
{
Description: "G",
guid: "c8e63b35",
parent: null,
Children: [
{
Description: "Z",
guid: "b1113b35",
parent: "c8e63b35",
Children: [
{
Description: "F",
guid: "d2cc2233",
parent: "b1113b35",
}
]
},
]
},
{
Description: "L",
guid: "a24a3b1a",
parent: null,
Children: [
{
Description: "K",
guid: "cd3b11caa",
parent: "a24a3b1a",
}
}
]
请帮我找到方法。 一个有效的算法将不胜感激,因为我在理解如何正确执行此操作方面存在问题。 在每种情况下,我都需要在递归结构中找到检查元素的特定位置,并将其推送到找到的元素子数组中。 我认为这是愚蠢且低效的。 有什么方法可以快速有效地做到这一点?
编辑:递归数组的格式错误。 现在应该没问题了。 我的数组没有以任何方式排序。
这个很好用,很容易阅读:
function flatToHierarchy (flat) {
var roots = [] // things without parent
// make them accessible by guid on this map
var all = {}
flat.forEach(function(item) {
all[item.guid] = item
})
// connect childrens to its parent, and split roots apart
Object.keys(all).forEach(function (guid) {
var item = all[guid]
if (item.parent === null) {
roots.push(item)
} else if (item.parent in all) {
var p = all[item.parent]
if (!('Children' in p)) {
p.Children = []
}
p.Children.push(item)
}
})
// done!
return roots
}
这就是我将如何做到的:
var flatArray = [{ Description: "G", guid: "c8e63b35", parent: null, }, { Description: "Z", guid: "b1113b35", parent: "c8e63b35", }, { Description: "F", guid: "d2cc2233", parent: "b1113b35", }, { Description: "L", guid: "a24a3b1a", parent: null, }, { Description: "K", guid: "cd3b11caa", parent: "a24a3b1a", }]; var recursiveArray = unflatten(flatArray); alert(JSON.stringify(recursiveArray, null, 4));
<script> function unflatten(items) { return items.reduce(insert, { res: [], map: {} }).res; } function insert(obj, item) { var parent = item.parent; var map = obj.map; map[item.guid] = item; if (parent === null) obj.res.push(item); else { var parentItem = map[parent]; if (parentItem.hasOwnProperty("Children")) parentItem.Children.push(item); else parentItem.Children = [item]; } return obj; } </script>
当然,这仅在您的flatArray
具有每个父项都出现在其子项之前的属性时才有效。
希望有帮助。
我试图用伪代码编写算法,最终得到几乎可以工作的 JS 代码(也许需要一些额外的验证/检查),但显示了解决问题的一般方法。
//Lets separate children (nodes with a parent) from roots (nodes without a parent)
var children = flatArray.filter(function(object){
return object.parent !== null;
});
var roots = flatArray.filter(function(object){
return object.parent === null;
});
//And add each child to the nodes tree
children.foreach(function(child){
recursiveAdd(roots, child);
});
//To add a children node, node tree is searched recursively for a parent
function recursiveAdd(nodes, child){
nodes.foreach(function(parent){
if(parent.guid === child.parent){
parent.Children = parent.Children | [];
parent.Children.add(child);
} else if(parent.Children) {
recursiveAdd(parent.Children, child);
}
});
}
//Temporary children array can be garbage collected
children = null;
//Resulting node tree
var recursiveArray = roots;
这个递归函数可能对你有好处:
var flatArray = [{ Description: "G", guid: "c8e63b35", parent: null, Children: [] }, { Description: "Z", guid: "b1113b35", parent: "c8e63b35", Children: [] }, { Description: "F", guid: "d2cc2233", parent: "b1113b35", Children: [] }, { Description: "L", guid: "a24a3b1a", parent: null, Children: [] }, { Description: "K", guid: "cd3b11caa", parent: "a24a3b1a", Children: [] }, ]; for (var i = 0; i < flatArray.length; i++) { recursive(flatArray[i]); } function recursive(a) { for (var i = 0; i < flatArray.length; i++) { if (flatArray[i].parent == a.guid) { var b = flatArray[i]; recursive(b); a.Children.push(b); } } } console.log(flatArray)
var flatArray = [ { Description: "G", guid: "c8e63b35", parent: null, }, { Description: "Z", guid: "b1113b35", parent: "c8e63b35", }, { Description: "F", guid: "d2cc2233", parent: "b1113b35", }, { Description: "L", guid: "a24a3b1a", parent: null, }, { Description: "K", guid: "cd3b11caa", parent: "a24a3b1a", }, ]; //for printing function htmlPrint(obj) { document.write('<pre>'+JSON.stringify(obj,null,2)+'</pre>'); }; var guids = {}; var roots = []; flatArray.forEach(function(node){ guids[node.guid] = node; //save into a hash node.Children = []; //make sure it has a children array //save it as root if it is a root if(node.parent === null){ roots.push(node);} }); flatArray.forEach(function(node){ //if it has a parent, add self to parent's children var parent = guids[node.parent]; if(parent) parent.Children.push(node); }); htmlPrint(roots);
您可以在 Angular 中使用波纹管代码。
flatToHierarchy(flat: any[], parent: any = null, Key: string = 'id', parentKey: string = 'parentId') {
var leafs: any = [];
if (!parent) {
leafs = flat.filter((x: { [x: string]: any; }) => x[parentKey] === null);
} else {
leafs = flat.filter((x: { [x: string]: any; }) => x[parentKey] === parent[Key]);
}
if (!leafs || leafs.length == 0) {
return;
} else {
leafs.forEach((item: { children: any[]; }) => {
item.children = [];
item.children = this.flatToHierarchy(flat, item);
});
}
return leafs;
}
像这样使用
this.flatToHierarchy(flatItems);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.