我有一个元素列表,每个元素都有一个ID和一个父ID。我想做的是检测此“层次结构”中是否存在循环,并显示哪个ID开始循环。
list = [
{
id: '1',
parent: '2'
},
{
id: '2',
parent: '3'
},
{
id: '3',
parent: '4'
},
{
//This id is causing the loop
id: '4',
parent: '1'
}
]
我已经尝试过构建树,它在没有循环的情况下可以工作,但是在没有循环的情况下可以工作:
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;
};
我也无法检测到何时出现循环。
我想返回导致循环的元素ID,以便我修复其背后的数据。
答案 0 :(得分:1)
您可以应用白色-灰色-黑色着色来检测在访问其后代时被(重新)访问的节点(我已将您的图形简化为一系列父子对):
graph = [
[2, 1],
[3, 2],
[1300023, 3],
[1, 1300023],
];
colors = {}
function visit(vertex) {
if (colors[vertex] === 'black') {
// black = ok
return;
}
if (colors[vertex] === 'grey') {
// grey = visited while its children are being visited
// cycle!
console.log('cycle', colors);
return;
}
// mark as being visited
colors[vertex] = 'grey';
// visit children
graph.forEach(edge => {
if (edge[0] === vertex)
visit(edge[1]);
});
// mark as visited and ok
colors[vertex] = 'black'
}
visit(1)
这种方法的一个很好的例证:https://algorithms.tutorialhorizon.com/graph-detect-cycle-in-a-directed-graph-using-colors/
答案 1 :(得分:0)
您可以收集对象中的所有节点和子节点,并通过访问一组访问节点来过滤所有节点。
无限数组包含导致循环引用的所有节点。
~>
pod 'Appsee', '2.5.0'