递归方式的层次树构造逻辑
Construction logic for Hierarchial tree in Recursion fashion
var cellData = [];
function constructCells(graph, cell) {
var cellDataObj = {};
var outgoingEdges = graph.getOutgoingEdges(cell);
cellDataObj.id = cell.id;
cellDataObj.value = cell.value;
if (outgoingEdges.length) {
cellDataObj.children = [];
_.each(outgoingEdges, vertex => {
const target = vertex.target;
var targetEdges = graph.getOutgoingEdges(target);
if (targetEdges.length) {
cellDataObj.children.push({
id: target.id,
value: target.value,
children: getChildrens(graph, target)
});
} else {
cellDataObj.children.push({ id: target.id, value: target.value });
}
});
}
cellData.push(cellDataObj);
}
function getChildrens(graph, cell) {
var cells = [];
var outgoingEdges = graph.getOutgoingEdges(cell);
_.each(outgoingEdges, vertex => {
cells.push({
id: vertex.target.id,
value: vertex.target.value
});
});
return cells;
}
上面的代码在第一级和第二级之前工作得很好,即直到 v3 节点,它构造 v4 和 v5 作为它的 childrens。但是我在这里的某个地方失去了逻辑,如果成立 children.
则无法为以下节点构建
结果是:
Looking forward for logic correction required for multilevel nesting
i.e for the level of V6 and V7 level nodes.
您可以考虑以下图片作为预期参考:
Flat 到 json 转换,抱歉,我无法 post 代码,因为包含库数据和代码需要清理。
要从平面列表到树,您不需要递归。反之亦然。
以下是使用单个循环从平面列表到嵌套结构的方法:
- 创建一个空对象,用于按 ID 存储节点
- 创建一个空对象来存储在我们处理它们的父节点
之前出现的节点
- 遍历所有条目
- 创建节点
- 检查我们之前是否看到节点将此 ID 引用为它们的父节点
- 如果我们这样做了,用这些节点预填充子数组
- 将节点添加到使用其 id 作为键的对象
- 检查对象是否已经包含节点的父节点
- 如果是,则将新节点推送到其父子数组
- 如果没有,将该节点索引为临时孤儿
- 检查节点是否为根节点,如果是则存储
- return根节点
在代码中:
const flat = [
{ id: 1, parentId: 3 },
{ id: 3, parentId: 8 },
{ id: 4, parentId: 6 },
{ id: 6, parentId: 3 },
{ id: 7, parentId: 6 },
{ id: 8, parentId: null },
{ id: 10, parentId: 8 },
{ id: 13, parentId: 14 },
{ id: 14, parentId: 10 }
];
const toTree = nodes => {
const index = {};
const orphans = {};
let root = null;
nodes.forEach(
({ id, parentId }) => {
const node = { id, children: orphans[id] || [] };
index[id] = node;
const parent = index[parentId];
if (!parent) {
if (orphans[parentId]) orphans[parentId].push(node)
else orphans[parentId] = [node];
} else {
parent.children.push(node);
}
if (parentId === null) root = node;
}
);
return root;
}
console.log(JSON.stringify(toTree(flat), null, 2));
返回平面列表:
- 从根节点开始调用
flatten
- 将根节点连接到结果数组
- 如果它有子节点,则使用根节点 ID 作为父节点 ID(即递归)展平每个子节点
const tree = {"id":8,"children":[{"id":3,"children":[{"id":1,"children":[]},{"id":6,"children":[{"id":4,"children":[]},{"id":7,"children":[]}]}]},{"id":10,"children":[{"id":14,"children":[{"id":13,"children":[]}]}]}]};
const flatten = (node, parentId = null) =>
[{ id: node.id, parentId }].concat(
node.children.flatMap(
child => flatten(child, node.id)
)
);
console.log(flatten(tree));
var cellData = [];
function constructCells(graph, cell) {
var cellDataObj = {};
var outgoingEdges = graph.getOutgoingEdges(cell);
cellDataObj.id = cell.id;
cellDataObj.value = cell.value;
if (outgoingEdges.length) {
cellDataObj.children = [];
_.each(outgoingEdges, vertex => {
const target = vertex.target;
var targetEdges = graph.getOutgoingEdges(target);
if (targetEdges.length) {
cellDataObj.children.push({
id: target.id,
value: target.value,
children: getChildrens(graph, target)
});
} else {
cellDataObj.children.push({ id: target.id, value: target.value });
}
});
}
cellData.push(cellDataObj);
}
function getChildrens(graph, cell) {
var cells = [];
var outgoingEdges = graph.getOutgoingEdges(cell);
_.each(outgoingEdges, vertex => {
cells.push({
id: vertex.target.id,
value: vertex.target.value
});
});
return cells;
}
上面的代码在第一级和第二级之前工作得很好,即直到 v3 节点,它构造 v4 和 v5 作为它的 childrens。但是我在这里的某个地方失去了逻辑,如果成立 children.
则无法为以下节点构建结果是:
Looking forward for logic correction required for multilevel nesting i.e for the level of V6 and V7 level nodes.
您可以考虑以下图片作为预期参考:
Flat 到 json 转换,抱歉,我无法 post 代码,因为包含库数据和代码需要清理。
要从平面列表到树,您不需要递归。反之亦然。
以下是使用单个循环从平面列表到嵌套结构的方法:
- 创建一个空对象,用于按 ID 存储节点
- 创建一个空对象来存储在我们处理它们的父节点 之前出现的节点
- 遍历所有条目
- 创建节点
- 检查我们之前是否看到节点将此 ID 引用为它们的父节点
- 如果我们这样做了,用这些节点预填充子数组
- 将节点添加到使用其 id 作为键的对象
- 检查对象是否已经包含节点的父节点
- 如果是,则将新节点推送到其父子数组
- 如果没有,将该节点索引为临时孤儿
- 检查节点是否为根节点,如果是则存储
- return根节点
在代码中:
const flat = [
{ id: 1, parentId: 3 },
{ id: 3, parentId: 8 },
{ id: 4, parentId: 6 },
{ id: 6, parentId: 3 },
{ id: 7, parentId: 6 },
{ id: 8, parentId: null },
{ id: 10, parentId: 8 },
{ id: 13, parentId: 14 },
{ id: 14, parentId: 10 }
];
const toTree = nodes => {
const index = {};
const orphans = {};
let root = null;
nodes.forEach(
({ id, parentId }) => {
const node = { id, children: orphans[id] || [] };
index[id] = node;
const parent = index[parentId];
if (!parent) {
if (orphans[parentId]) orphans[parentId].push(node)
else orphans[parentId] = [node];
} else {
parent.children.push(node);
}
if (parentId === null) root = node;
}
);
return root;
}
console.log(JSON.stringify(toTree(flat), null, 2));
返回平面列表:
- 从根节点开始调用
flatten
- 将根节点连接到结果数组
- 如果它有子节点,则使用根节点 ID 作为父节点 ID(即递归)展平每个子节点
const tree = {"id":8,"children":[{"id":3,"children":[{"id":1,"children":[]},{"id":6,"children":[{"id":4,"children":[]},{"id":7,"children":[]}]}]},{"id":10,"children":[{"id":14,"children":[{"id":13,"children":[]}]}]}]};
const flatten = (node, parentId = null) =>
[{ id: node.id, parentId }].concat(
node.children.flatMap(
child => flatten(child, node.id)
)
);
console.log(flatten(tree));