我有一个带有< code>parent字段的“page”对象列表。该父字段引用了列表中的另一个对象。我想从基于此字段的列表中创建一个树层次结构。
以下是我的原始列表:
[
{
id: 1,
title: 'home',
parent: null
},
{
id: 2,
title: 'about',
parent: null
},
{
id: 3,
title: 'team',
parent: 2
},
{
id: 4,
title: 'company',
parent: 2
}
]
我想把它转换成这样的树形结构:
[
{
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
}
]
]
我希望有一个可重用的函数,我可以随时对任意列表调用它。有谁知道处理这个问题的好方法吗?任何帮助或建议将不胜感激!
公认的答案在我的研究中非常有帮助,但是,我必须在心里解析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;
};
这是与公认答案相同的代码,但有一些注释来解释发生了什么。这是一个用例,它将生成一个div列表,根据级别使用内联< code>marginLeft缩进呈现到页面上:
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))
如果您想运行它,请使用Codepen:https://codepen.io/roblevin/pen/gVRowd?editors=0010
在我看来,关于此解决方案的有趣之处在于,查找表使用项的 ID 作为键保持平面,并且只有根对象被推送到生成的树列表中。然而,由于JavaScript对象的参照性质,根有它的子级,子级有它的子级,依此类推,但它本质上是从根部连接的,因此是树状的。
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) {
if (lookup[obj[parentAttr]] !== undefined) {
lookup[obj[parentAttr]][childrenAttr].push(obj);
} else {
//console.log('Missing Parent Data: ' + obj[parentAttr]);
treeList.push(obj);
}
} else {
treeList.push(obj);
}
});
return treeList;
};
小提琴
问题内容: 我有一个带有字段的“页面”对象列表。此父字段引用列表中的另一个对象。我想基于此字段从此列表创建树层次结构。 这是我原始列表的样子: 我想将其转换为这样的树结构: 我希望可以在任何时候针对任意列表调用的可重用函数。有人知道解决这个问题的好方法吗?任何帮助或建议,将不胜感激! 问题答案: 小提琴
问题内容: 我在列表中有一个字符串路径集合,例如[“ x1 / x2 / x3”,“ x1 / x2 / x4”,“ x1 / x5”]。我需要从该列表构造一个树状结构,可以对其进行迭代以获得漂亮的打印树。像这样 有什么想法/建议吗?我认为可以通过处理字符串列表来首先解决该问题。编辑:选择的正确答案是一种优雅的实现,其他建议也很好。 问题答案: 遵循可访问树的幼稚实现的实现: 访客模式的界面: 访
我们正在创建一个REST API,目前我们有两种方法来定义资源。 基本上,我们有、和,其中一个有n个和一个有n个。 分层方法 该层次结构在URI中可见 要搜索所有图像,我们需要一个搜索资源 平进路 我们还需要考虑移动和修改。
问题内容: 我有课: 然后创建对象: 尝试获取所有字段后,我打电话 但是我只有一个数组 如何从所有类的所有字段包括扩展? 问题答案: 请尝试以下操作:
问题内容: 我有对象T的列表,它具有父属性,其中顶级对象的父属性为null。我想将所有对象放入TreeSet(或TreeMap)中。顶级对象将是所有没有父级的根对象(父级为null),并且它们的下级将是其子级。 像这样 所以我可以得到Ra并找到它的子代(Ca1,Ca2,Ca11,Ca12…。) 更新:很抱歉,可能不清楚,节点指向父节点,如果parent为null,则它们是根节点。问题是父母需要了解
问题内容: 像这样对表格进行排序的最佳方法是什么: 要通过分级排序,它 的ID 或 名字 : “比萨饼” //节点1 “piperoni” //节点1.1 “奶酪” //节点1.2 “额外的奶酪” //节点1.2.1 “vegetariana” //节点1.3 “汉堡” //节点2 ‘咖啡’//节点3 编辑: 名称 末尾的数字是为了更好地可视化strucutre,而不是用于排序。 编辑2: 正如多