繁体   English   中英

Javascript 阵列被填充,我不明白如何

[英]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下排序的。 lookuplistnodes和查找列表上完成。 我再次觉得我缺少对 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'

同样的事情发生在你的代码中: nodestoplevelNodeslookupList都持有对它们内部相同节点对象的引用,当你在一个地方发生变异时,它也会在其他地方更新。

基本上,这是具有魔力的行:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM