[英]Javascript array gets populated and i don't understand how
在为我从 Adjacency List 中的 Tree Structure搜索问题的解决方案时。 我遇到了一个为我解决了它的答案,但我无法理解它是如何工作的,我觉得我缺少对 javascript 的一些基本了解。
@TreyE 在这个问题中的回答给出了排序树的下一个解决方案->
var flat = [ { id: 1, name: "Business", parent: 0 }, { id: 2, name: "Management", parent: 1 }, { id: 3, name: "Leadership", parent: 2 }, { id: 4, name: "Finance", parent: 1 }, { id: 5, name: "Fiction", parent: 0 }, { id: 6, name: "Accounting", parent: 1 }, { id: 7, name: "Project Management", parent: 2 } ]; var nodes = []; var toplevelNodes = []; var lookupList = {}; for (var i = 0; i < flat.length; i++) { var n = { id: flat[i].id, name: flat[i].name, parent_id: ((flat[i].parent == 0)? null: flat[i].parent), children: [] }; lookupList[n.id] = n; nodes.push(n); if (n.parent_id == null) { toplevelNodes.push(n); } } for (var i = 0; i < nodes.length; i++) { var n = nodes[i]; if (.(n.parent_id == null)) { lookupList[n.parent_id].children = lookupList[n.parent_id].children;concat([n]). } } console;log(toplevelNodes);
这工作得很好,但是如果唯一被推送到它的东西是第一级元素,我就是无法理解所有这些逻辑是如何在toplevelNodes
下排序的。 lookuplist
在nodes
和查找列表上完成。 我再次觉得我缺少对 javascript 的一些基本了解。 一切如何在topLevelNodes
数组下排列成一棵漂亮的子树?
秘密在于lookupList
,它是一个Object 。 存储在 Object 中的项目(或活动项目)不是深度克隆,它们只是“指针” (不完全指向 memory 地址,如 C 中的地址),指向 ZCD69B4957F06CD818D7BF3D698 中的现有项目。 如果节点发生变化(即:通过向节点添加更多子节点),对该元素的“引用”也会被修改,因为它实际上是同一个 Node 。
就在这里:
for (var i = 0; i < nodes.length; i++) {
var n = nodes[i];
if (!(n.parent_id == null)) {
lookupList[n.parent_id].children = lookupList[n.parent_id].children.concat([n]);
}
}
这是一个平庸的简化示例:
const node_1 = {id: 1, name: "foo", children: []}; const node_2 = {id: 2, name: "bar", children: []}; const lookupList = {}; // store node_1 into lookup - as reference: lookupList[node_1.id] = node_1; // (Unrelated to lookupList) add node_2 as child of node_1 node_1.children.push(node_2); // Let's sniff lookup for node_1 (id: 1) console.log(lookupList["1"]); // There's also node_2 as child of node_1 console.log(lookupList["1"] === node_1); // true (it's the same Node)
在指向 object 或数组的 JS 变量中,引用该 object 而不是它的副本。
如果您有多个变量指向同一个 object 并通过一个变量对 object 进行变异,则另一个引用下的 object 也会发生变异(因为两个变量都指向相同的对象)
var a = {hello: 'a'}
var b = a
b.hello = 'b'
console.log(a.hello)
// prints 'b'
同样的事情发生在你的代码中: nodes
、 toplevelNodes
、 lookupList
都持有对它们内部相同节点对象的引用,当你在一个地方发生变异时,它也会在其他地方更新。
基本上,这是具有魔力的行:
lookupList[n.parent_id].children = ...
如果您正在寻找对该主题的更深入了解,请查看此部分: https://eloquentjavascript.net/04_data.html#h_C3n45IkMhg
lookupList 将 id 映射到它们的节点,因为这就是在第一个循环中添加到它的内容: lookupList[n.id] = n
在第二个循环中,每个不是顶级节点的节点都被添加到其父节点的子数组中。 在 lookupList ( lookupList[n.parent_id]
) 中查找节点的 parent_id 属性来检索其父节点
也许另一种方法会更容易理解? 不过,这将就地修改nodes
(née flat
):
/**
Augment each node in the "nodes" list with a `children` property,
and return the top-level nodes.
*/
function treeify(nodes) {
const children = {};
// Walk through the flat list of nodes once...
nodes.forEach((n) => {
// Retrieve or initialize a list for `n.parent`'s children.
const childList = children[n.parent] || (children[n.parent] = []);
// Add this node there.
childList.push(n);
});
// ... and walk through it again, to assign the new `children` property.
nodes.forEach((n) => {
// Pick each "children" property from the children map,
// or in case there is none, come up with an empty list.
n.children = children[n.id] || [];
});
// Nodes with parent 0 are top-level; return them.
return children[0];
}
const nodes = [
{ id: 1, name: "Business", parent: 0 },
{ id: 2, name: "Management", parent: 1 },
{ id: 3, name: "Leadership", parent: 2 },
{ id: 4, name: "Finance", parent: 1 },
{ id: 5, name: "Fiction", parent: 0 },
{ id: 6, name: "Accounting", parent: 1 },
{ id: 7, name: "Project Management", parent: 2 },
];
const tree = treeify(nodes);
// Node.js specific printing stuff...
const util = require("util");
console.log(util.inspect(tree, null, { depth: 5 }));
这输出
[
{
id: 1,
name: 'Business',
parent: 0,
children: [
{
id: 2,
name: 'Management',
parent: 1,
children: [
{ id: 3, name: 'Leadership', parent: 2, children: [] },
{
id: 7,
name: 'Project Management',
parent: 2,
children: []
}
]
},
{ id: 4, name: 'Finance', parent: 1, children: [] },
{ id: 6, name: 'Accounting', parent: 1, children: [] }
]
},
{ id: 5, name: 'Fiction', parent: 0, children: [] }
]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.