Tru*_*an1 18 javascript arrays tree json hierarchy
我有一个带有parent字段的"页面"对象列表.此父字段引用列表中的另一个对象.我想基于此字段从此列表中创建树层次结构.
这是我的原始列表:
[
{
id: 1,
title: 'home',
parent: null
},
{
id: 2,
title: 'about',
parent: null
},
{
id: 3,
title: 'team',
parent: 2
},
{
id: 4,
title: 'company',
parent: 2
}
]
Run Code Online (Sandbox Code Playgroud)
我想将它转换为这样的树结构:
[
{
id: 1,
title: 'home',
parent: null
},
{
id: 2,
title: 'about',
parent: null,
children: [
{
id: 3,
title: 'team',
parent: 2
},
{
id: 4,
title: 'company',
parent: 2
}
]
]
Run Code Online (Sandbox Code Playgroud)
我希望有一个可重用的函数,我可以随时调用任意列表.有人知道处理这个问题的好方法吗?任何帮助或建议将不胜感激!
Ama*_*dan 49
function treeify(list, idAttr, parentAttr, childrenAttr) {
if (!idAttr) idAttr = 'id';
if (!parentAttr) parentAttr = 'parent';
if (!childrenAttr) childrenAttr = 'children';
var treeList = [];
var lookup = {};
list.forEach(function(obj) {
lookup[obj[idAttr]] = obj;
obj[childrenAttr] = [];
});
list.forEach(function(obj) {
if (obj[parentAttr] != null) {
lookup[obj[parentAttr]][childrenAttr].push(obj);
} else {
treeList.push(obj);
}
});
return treeList;
};
Run Code Online (Sandbox Code Playgroud)
接受的答案对我的研究非常有帮助,但是,我必须在精神上解析我理解的 id 参数,使函数更灵活,但对于算法的新手来说,可能有点难以推理。
如果其他人有这个困难,这里有基本相同的代码,但可能更容易理解:
const treeify = (arr, pid) => {
const tree = [];
const lookup = {};
// Initialize lookup table with each array item's id as key and
// its children initialized to an empty array
arr.forEach((o) => {
lookup[o.id] = o;
lookup[o.id].children = [];
});
arr.forEach((o) => {
// If the item has a parent we do following:
// 1. access it in constant time now that we have a lookup table
// 2. since children is preconfigured, we simply push the item
if (o.parent !== null) {
lookup[o.parent].children.push(o);
} else {
// no o.parent so this is a "root at the top level of our tree
tree.push(o);
}
});
return tree;
};
Run Code Online (Sandbox Code Playgroud)
它与接受的答案相同,并带有一些注释来解释正在发生的事情。这是一个用例,它将导致marginLeft根据级别使用内联缩进呈现到页面的 div 列表:
const arr = [
{id: 1, title: 'All', parent: null},
{id: 2, title: 'Products', parent: 1},
{id: 3, title: 'Photoshop', parent: 2},
{id: 4, title: 'Illustrator', parent: 2},
{id: 4, title: 'Plugins', parent: 3},
{id: 5, title: 'Services', parent: 1},
{id: 6, title: 'Branding', parent: 5},
{id: 7, title: 'Websites', parent: 5},
{id: 8, title: 'Pen Testing', parent: 7}];
const render = (item, parent, level) => {
const div = document.createElement('div');
div.textContent = item.title;
div.style.marginLeft = level * 8 + 'px';
parent.appendChild(div);
if (item.children.length) {
item.children.forEach(child => render(child, div, ++level));
}
return parent;
}
const fragment = document.createDocumentFragment();
treeify(arr)
.map(item => render(item, fragment, 1))
.map(frag => document.body.appendChild(frag))
Run Code Online (Sandbox Code Playgroud)
Codepen 如果你想运行它:https ://codepen.io/roblevin/pen/gVRowd?editors=0010
在我看来,这个解决方案的有趣部分是查找表使用项目的 ID 作为键保持平坦,并且只有根对象被推送到结果树列表中。然而,由于 JavaScript 对象的引用性质,根有它的孩子,孩子有他们的孩子,等等,但它本质上是从根连接的,因此像树一样。
| 归档时间: |
|
| 查看次数: |
18711 次 |
| 最近记录: |