【问题标题】:Find a child by id in JS Object and push to it在 JS 对象中通过 id 找到一个孩子并推送给它
【发布时间】:2018-07-02 04:35:42
【问题描述】:

我有一个这样的对象,我想通过 id 找到一个孩子并将一个新孩子推送给它。

{
'id': '234567869',
'name': 'Lao Lao',
'title': 'general manager',
'children': [{
    'id': '467876756634',
    'name': 'Bo Miao',
    'title': 'department manager'
}, {
    'id': '2345666078',
    'name': 'Su Miao',
    'title': 'department manager',
    'children': [{
        'id': '898735342',
        'name': 'Tie Hua',
        'title': 'senior engineer'
    }, {
        'id': '7697347548',
        'name': 'Hei Hei',
        'title': 'senior engineer',
        'children': [{
            'id': '123415640',
            'name': 'Pang Pang',
            'title': 'engineer'
        }, {
            'id': '1237450976',
            'name': 'Xiang Xiang',
            'title': 'UE engineer'
        }]
    }]
}, {
    'id': '6968756535',
    'name': 'Yu Jie',
    'title': 'department manager'
}, {
    'id': '236448654',
    'name': 'Chun Miao',
    'title': 'department manager'
}, {
    'id': '356898765',
    'name': 'Yu Tie',
    'title': 'department manager'
}]}

我想向 id 为“898735342”或“234567869”的对象添加一个子对象。

我使用了这个递归函数,但不起作用。这应该在我们的对象中通过“id”进行搜索,并将“newObj”作为子对象推送给它。

var newObj = {
    'id': '999999999',
    'name': 'new name',
    'title': 'new added child',
};

function findNodeAndUpdate(idToFind, bigObjectToSearch, newObj) {
    var i, currentChild, result;
    if (idToFind == bigObjectToSearch.id) {
        bigObjectToSearch.children.push(newObj);
        return true;
    } else {
        // Use a for loop instead of forEach to avoid nested functions
        // Otherwise "return" will not work properly
        for (i = 0; i < bigObjectToSearch.children.length; i += 1) {
            currentChild = bigObjectToSearch.children[i];
            // Search in the current child
            result = findNodeAndUpdate(idToFind, currentChild, newObj);
            // Return the result if the node has been found
            if (result !== false) {
                bigObjectToSearch.children.push(newObj);
                return true;
            }
        }
        // The node has not been found and we have no more options
        return false;
    }
}

另一个仍然不起作用的功能:

function findObjectById(root, id) {
    if (root.id == id){
        return root;
    }
    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);
            }
        }
    }
};

【问题讨论】:

  • 提示:遍历整个树一次,并通过它们的 id 将所有节点存储在一个对象中。这使得通过 id 进一步查找一个简单的node = nodesById[id]
  • @Thomas 我在我的问题 (findObjectById) 中添加了一个新函数,它的作用与您提到的完全相同,但它不起作用,我不知道出了什么问题。

标签: javascript object search


【解决方案1】:

请尝试以下代码:

var obj = {
    'id': '234567869',
    'name': 'Lao Lao',
    'title': 'general manager',
    'children': [{
        'id': '467876756634',
        'name': 'Bo Miao',
        'title': 'department manager'
    }, {
        'id': '2345666078',
        'name': 'Su Miao',
        'title': 'department manager',
        'children': [{
            'id': '898735342',
            'name': 'Tie Hua',
            'title': 'senior engineer'
        }, {
            'id': '7697347548',
            'name': 'Hei Hei',
            'title': 'senior engineer',
            'children': [{
                'id': '123415640',
                'name': 'Pang Pang',
                'title': 'engineer'
            }, {
                'id': '1237450976',
                'name': 'Xiang Xiang',
                'title': 'UE engineer'
            }]
        }]
    }, {
        'id': '6968756535',
        'name': 'Yu Jie',
        'title': 'department manager'
    }, {
        'id': '236448654',
        'name': 'Chun Miao',
        'title': 'department manager'
    }, {
        'id': '356898765',
        'name': 'Yu Tie',
        'title': 'department manager'
    }]
};

var newObj = {
    'id': '999999999',
    'name': 'new name',
    'title': 'new added child',
};

function findNodeAndUpdate(idToFind, bigObjectToSearch, newObj) {
    var i, currentChild, result;
    if (idToFind == bigObjectToSearch.id) {
        bigObjectToSearch.children = bigObjectToSearch.children || [];
        bigObjectToSearch.children.push(newObj);
        return true;
    } else if (bigObjectToSearch.children) {
        for (i = 0; i < bigObjectToSearch.children.length; i += 1) {
            currentChild = bigObjectToSearch.children[i];
            // Search in the current child
            if(findNodeAndUpdate(idToFind, currentChild, newObj)){
                break;
            }
        }
        return false;
    }
    return false;
}

findNodeAndUpdate('898735342', obj, newObj);

console.log(obj); 

要删除 obj,

function deleteNode(idToFind, bigObjectToSearch) {
    var i, currentChild, result;
    if (idToFind == bigObjectToSearch.id) {
        return true;
    } else if (bigObjectToSearch.children) {
        for (i = 0; i < bigObjectToSearch.children.length; i += 1) {
            currentChild = bigObjectToSearch.children[i];
            // Search in the current child
            if(deleteNode(idToFind, currentChild)){
                //delete bigObjectToSearch.children[i];
                bigObjectToSearch.children.splice(i,1);
                break;
            };
        }
        return false;
    }
    return false;
}

希望对你有帮助:)

【讨论】:

  • 它有一个错误,它总是将新对象添加到根对象,即使我们正在更新嵌套的子对象。
  • 如果我想通过它的 id 删除一个节点怎么办。比如我想删除id为“6968756535”的节点?
  • 我已编辑 ans 以删除节点。请尝试:)
  • 请立即尝试 :)
  • 它将孩子设置为空,我希望将其删除。有可能吗?
【解决方案2】:

您可以使用以下代码。

var searchObj = {
    'id': '234567869',
    'name': 'Lao Lao',
    'title': 'general manager',
    'children': [{
        'id': '467876756634',
        'name': 'Bo Miao',
        'title': 'department manager'
    }, {
        'id': '2345666078',
        'name': 'Su Miao',
        'title': 'department manager',
        'children': [{
            'id': '898735342',
            'name': 'Tie Hua',
            'title': 'senior engineer'
        }, {
            'id': '7697347548',
            'name': 'Hei Hei',
            'title': 'senior engineer',
            'children': [{
                'id': '123415640',
                'name': 'Pang Pang',
                'title': 'engineer'
            }, {
                'id': '1237450976',
                'name': 'Xiang Xiang',
                'title': 'UE engineer'
            }]
        }]
    }, {
        'id': '6968756535',
        'name': 'Yu Jie',
        'title': 'department manager'
    }, {
        'id': '236448654',
        'name': 'Chun Miao',
        'title': 'department manager'
    }, {
        'id': '356898765',
        'name': 'Yu Tie',
        'title': 'department manager'
    }]
};

function findNodeAndUpdate(bigObjectToSearch, idToFind, newObj) {
    if (idToFind) {
        findNodeAndUpdate.searchValue = idToFind;
    }
    if (newObj) {
        findNodeAndUpdate.pushValue = newObj;
    }
    if (isArray(bigObjectToSearch)) {
        traverseArray(bigObjectToSearch)
    } else if ((typeof bigObjectToSearch === 'object') && (bigObjectToSearch !== null)) {
        traverseObject(bigObjectToSearch)
    } else {

    }
}

function traverseArray(arr) {
    arr.forEach(function(data) {
        findNodeAndUpdate(data)
    })
}

function traverseObject(obj) {
    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            if (key === "id" && obj[key] == findNodeAndUpdate.searchValue) {
                if (obj.hasOwnProperty("children")) {
                    obj.children.push(findNodeAndUpdate.pushValue);
                } else {
                    obj["children"] = [];
                    obj.children.push(findNodeAndUpdate.pushValue);

                }
                break;
            } else {
                findNodeAndUpdate(obj[key]);
            }
        }
    }
}

function isArray(o) {
    return Object.prototype.toString.call(o) === '[object Array]'
}
findNodeAndUpdate(searchObj, "898735342", {
    'id': '999999999',
    'name': 'new name',
    'title': 'new added child',
});

【讨论】:

    【解决方案3】:

    试试这个,核心是循环,当你将对象作为参数传递时,无论函数或循环中的对象发生什么变化,都会改变函数外的对象,这是最重要的

    let oldObj = {
        "id": "234567869",
        "name": "Lao Lao",
        "title": "general manager",
        "children": [{
            "id": "467876756634",
            "name": "Bo Miao",
            "title": "department manager"
        }, {
            "id": "2345666078",
            "name": "Su Miao",
            "title": "department manager",
            "children": [{
                "id": "898735342",
                "name": "Tie Hua",
                "title": "senior engineer"
            }, {
                "id": "7697347548",
                "name": "Hei Hei",
                "title": "senior engineer",
                "children": [{
                    "id": "123415640",
                    "name": "Pang Pang",
                    "title": "engineer"
                }, {
                    "id": "1237450976",
                    "name": "Xiang Xiang",
                    "title": "UE engineer"
                }]
            }]
        }, {
            "id": "6968756535",
            "name": "Yu Jie",
            "title": "department manager"
        }, {
            "id": "236448654",
            "name": "Chun Miao",
            "title": "department manager"
        }, {
            "id": "356898765",
            "name": "Yu Tie",
            "title": "department manager"
        }]
    };
    
    let result = {
        "id": "234567869",
        "name": "Lao Lao",
        "title": "general manager",
        "children": [{
            "id": "467876756634",
            "name": "Bo Miao",
            "title": "department manager"
        }, {
            "id": "2345666078",
            "name": "Su Miao",
            "title": "department manager",
            "children": [{
                "id": "898735342",
                "name": "Tie Hua",
                "title": "senior engineer"
    
            }, {
                "id": "7697347548",
                "name": "Hei Hei",
                "title": "senior engineer",
                "children": [{
                    "id": "123415640",
                    "name": "Pang Pang",
                    "title": "engineer"
                }, {
                    "id": "1237450976",
                    "name": "Xiang Xiang",
                    "title": "UE engineer"
                }]
            }]
        }, {
            "id": "6968756535",
            "name": "Yu Jie",
            "title": "department manager"
        }, {
            "id": "236448654",
            "name": "Chun Miao",
            "title": "department manager"
        }, {
            "id": "356898765",
            "name": "Yu Tie",
            "title": "department manager"
        }, {
            'id': '999999999',
            'name': 'new name',
            'title': 'new added child',
        }]
    };
    
    var newObj = {
        'id': '999999999',
        'name': 'new name',
        'title': 'new added child',
    };
    
    function findIdAppendObj(newObj, oldObj, idToFind) {
    
        if (oldObj.id === idToFind) {
    
            if (oldObj.children) {
                oldObj.children.push(newObj);
            } else {
                oldObj.children = [newObj];
            }
    
            return oldObj;
    
        } else {
            if (oldObj.children) {
                oldObj.children.forEach(function(child) {
                    findIdAppendObj(newObj, child, idToFind);
                });
            }
        }
    
        return oldObj;
    
    }
    
    let testResult = findIdAppendObj(newObj, oldObj, '234567869');
    console.log(JSON.stringify(testResult) === JSON.stringify(result));
    

    【讨论】:

      【解决方案4】:

      我在我的问题 (findObjectById) 中添加了一个新函数,它与您提到的完全相同

      不完全是

      但它不起作用,我不知道出了什么问题。

      此时root.children.length 的条件始终为true,因此您在返回之前永远不会超过第一个孩子。

      但我的意思更像是这样的:

      let root = //...
      let nodesById = Object.create(null);
      
      //map nodes by id
      (function traverse(node){
        nodesById[id] = node;
        if(node.children)
          node.children.forEach(traverse);
      })( root );
      

      你的查找归结为这个

      function findObjectById(id) {
        return nodesById[id];
      }
      

      【讨论】:

        猜你喜欢
        • 2020-01-14
        • 2016-06-16
        • 1970-01-01
        • 2017-10-19
        • 2014-07-21
        • 2015-10-13
        • 1970-01-01
        • 1970-01-01
        • 2018-10-26
        相关资源
        最近更新 更多