【问题标题】:How to add an object to a nested javascript object using a parent id如何使用父 ID 将对象添加到嵌套的 javascript 对象
【发布时间】:2012-10-05 15:53:34
【问题描述】:

在我的应用程序中,我基于来自服务器的 JSON 响应创建了一个 JavaScript 对象,类似于:

{
  name: "root",
  id: 1,
  children: [
    {
      name: "child one",
      id: 11,
      children: [
       {name: "grand child 1", id: 111, children: []},
       {name: "grand child 2", id: 112, children: []}
      ]
   },
   {
     name: "child two",
     id: 12,
     children: []
   }
  ]
}

我新建一个节点如:

 {name: "grandchild three", id: 113, children:[]}

考虑到这一点,我如何将这个新孙子添加到其 id 为 11 的父级?请注意,我不知道 id == 11 节点的静态路径,所以我想知道如何在知道它是 id 的情况下获取该节点。

编辑:请注意,真实情况下的 id 不会对对象的路径进行编码。我创建了这个简单的示例来演示我正在处理的数据结构。但是我无法在我的真实应用程序中使用它的 id 检索到对象的路径。

【问题讨论】:

  • object.children[0].children.push(newobject) 其中 object 是您的原始对象,newobject 是您的新节点。
  • 感谢您的快速响应。但是,如果我只有 parent id,如何找到对象的路径?

标签: javascript json rest


【解决方案1】:

看到这个小提琴:http://jsfiddle.net/2Dvws/

它将通过 ID 查找对象。并推新子。由于 Javascript 中的每个对象都是引用,因此您可以将其作为 var 返回。

var ob = {
    name: "root",
    id: 1,
    children: [
        {
        name: "child one",
        id: 11,
        children: [
            {
            name: "grand child 1",
            id: 111,
            children: []},
        {
            name: "grand child 2",
            id: 112,
            children: []}
        ]},
    {
        name: "child two",
        id: 12,
        children: []}
    ]
};

将返回找到的元素的函数。将查看所有子元素。

function findObjectById(root, id) {
    if (root.children) {
        for (var k in root.children) {
            if (root.children[k].id == id) {
                return root.children[k];
            }
            else if (root.children.length) {
                return findObjectById(root.children[k], id);
            }
        }
    }
};

var bla = findObjectById(ob, 111);

console.log(bla);
bla.children.push({
        name: "child x",
        id: 1111,
        children: []
});
console.log(ob);

输出是 id 为 111 的孩子将有 1 个 id 为 1111 的孩子 ​

【讨论】:

  • 谢谢!这是考虑我的嵌套树结构的唯一答案。
  • 你必须注意,函数也可以返回null,然后你不能做bla.children.push,因为blaNULL
【解决方案2】:

我假设 id 由 parent-id 加上子数组中的索引(1 到 9)组成?然后你可以这样:

var rootobj = {…};
var newnode = {name: "grandchild three", id: 113, children:[]};

var id = ""+newnode.id;
var cur = [rootobj];
for (var i=0; i<id.length-i; i++)
    cur = cur[id.charAt(i)-1].children;
cur[id.charAt(i)-1] = newnode;

【讨论】:

  • 该死,你太聪明了!不,我不能假设身份证是那种形式。我只是做了这个简单的例子来帮助讨论这个问题。我正在使用的真实 API 中的 id 是独立于对象路径生成的。
  • 好的,那么你怎么知道节点的路径呢?或者你根本不知道,需要为你知道id的父节点做一个full tree search?这应该不会太难。
【解决方案3】:

Niels 的回答是一个好的开始,但并未完全遍历树(例如,如果您要查找的节点是根的第二个子节点的子节点,它将中断)。如果根是您要查找的 id,它也会中断。以下是我的改进:

  function findObjectByID(root, id) {
    if (root.name == id){
      return root;
    }
    if (root.children) {
      for (var k in root.children) {
        if (root.children[k].name == id) {
          return root.children[k];
        }
        else if (root.children[k].children) {
          result = findObjectByID(root.children[k], id);
          if (result) {
            return result;
          }
        }
      }
    }
  };

【讨论】:

    【解决方案4】:

    这个怎么样。

    for(var a = 0; a < object.length; a++) {
        for(var b = 0; b < obj.children.length; b++) {
            if(object[a].children[b].id == 11) {
               object[a].children[b].children.push({
                    name: "grandchild three", 
                    id: 113, 
                    children: []
                });
            }
        }
    }
    

    【讨论】:

    • 这会遍历树吗?看起来它只搜索一个节点的子节点。问题是我不知道我的节点有多深,我只有它的 id。
    • 更新它以支持遍历树。
    • 好的,我明白了。所以我需要在树上做一个嵌套搜索,找到我要插入的节点,然后添加到它的子节点。但是为了获得完整和正确的答案,我认为您应该更新您的答案以使用递归或其他形式的树搜索算法。当前形式假设我的数据结构只有两层深。这不能用可以在任何叶子上生长的嵌套树来假设。再次感谢!
    • @Austin:这并没有真正遍历树,而只是循环遍历根节点的子节点。
    • 没问题。下一次将有助于更具体地说明您的问题并将其包括在内。 @Bergi 我在评论后意识到这一点。我的意思是遍历子节点。
    【解决方案5】:

    这是使用object-scan 的解决方案。使用库应该使其更具可读性和可维护性。

    // const objectScan = require('object-scan');
    
    const insert = (haystack, parentId, node) => objectScan(['**.id'], {
      abort: true,
      rtn: 'bool',
      filterFn: ({ value, parent }) => {
        if (value === parentId) {
          parent.children.push(node);
          return true;
        }
        return false;
      }
    })(haystack);
    
    const obj = { name: 'root', id: 1, children: [ { name: 'child one', id: 11, children: [ { name: 'grand child 1', id: 111, children: [] }, { name: 'grand child 2', id: 112, children: [] } ] }, { name: 'child two', id: 12, children: [] } ] };
    
    console.log(insert(obj, 11, { name: "grandchild three", id: 113, children: [] })); // true iff inserted
    // => true
    
    console.log(obj);
    // => { name: 'root', id: 1, children: [ { name: 'child one', id: 11, children: [ { name: 'grand child 1', id: 111, children: [] }, { name: 'grand child 2', id: 112, children: [] }, { name: 'grandchild three', id: 113, children: [] } ] }, { name: 'child two', id: 12, children: [] } ] }
    .as-console-wrapper {max-height: 100% !important; top: 0}
    &lt;script src="https://bundle.run/object-scan@13.8.0"&gt;&lt;/script&gt;

    免责声明:我是object-scan的作者

    【讨论】:

      猜你喜欢
      • 2023-01-12
      • 2021-09-16
      • 2016-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多