Javascript 如何检查嵌套对象是否是未使用jQuery的另一个对象的后代

Javascript 如何检查嵌套对象是否是未使用jQuery的另一个对象的后代,javascript,lodash,Javascript,Lodash,我有以下目标。我想做的是提供一个函数来指定给定对象是否是父对象id的后代。例如,我想这样做:lodash是受欢迎的 isThisDescendant(7,1) //true isThisDescendant(1,7) //false isThisDescendant(7,3) //false isThisDescendant(3,2) //true object = { children : [ { name: 'a',

我有以下目标。我想做的是提供一个函数来指定给定对象是否是父对象id的后代。例如,我想这样做:lodash是受欢迎的

isThisDescendant(7,1) //true
isThisDescendant(1,7) //false
isThisDescendant(7,3) //false
isThisDescendant(3,2) //true

object = {
    children : [
        {
            name: 'a',
            id: 1,
            children: [
                {
                    name: 'b',
                    id: 2,
                    children: [
                        {
                            name: 'c',
                            id: 3,
                            children: []
                        },
                        {
                            name: 'cc',
                            id: 4,
                            children: []
                        }                       
                    ]
                },
                {
                    name: 'ba',
                    id: 6,
                    children: [
                        {
                            name: 'c',
                            id: 8,
                            children: []
                        },
                        {
                            name: 'cd',
                            id: 7,
                            children: []
                        }                       
                    ]
                }               
            ]
        },
        {
            name: 'bb',
            id: 10,
            children: []
        }
    ]
}

有许多解决方案,但要有效,需要某些假设:

  • 这是一件一次性的事情还是需要不断地询问

    如果是一次性操作,那么您可能可以进行简单的广度优先搜索来查找父项,然后检查其子项是否包含您要查找的
    id
    。这是O(n)

    如果不是,那么您应该构建一个查找表
    (id,instance)
    ,然后使用该表查找您的父项并进行检查。这或多或少是O(1)到O(logn),因为子对象的大小远远小于整个集合的大小

  • 子数组是否已排序

    如果对数组进行了排序,那么一旦有了父实例,就可以对子数组执行二进制搜索以进一步优化它


  • 在这里,您将需要两个步骤——爬行树以找到“容器”,然后从容器向下爬行以找到后代

    const对象={
    儿童:[
    {
    名称:‘a’,
    id:1,
    儿童:[
    {
    名称:‘b’,
    id:2,
    儿童:[
    {
    名称:‘c’,
    id:3,
    儿童:[]
    },
    {
    姓名:'cc',
    id:4,
    儿童:[]
    }                       
    ]
    },
    {
    姓名:‘ba’,
    id:6,
    儿童:[
    {
    名称:‘c’,
    id:8,
    儿童:[]
    },
    {
    名称:“cd”,
    id:7,
    儿童:[]
    }                       
    ]
    }               
    ]
    },
    {
    名称:“bb”,
    id:10,
    儿童:[]
    }
    ]
    }
    函数是其子体(子体ID、容器ID、根=对象、foundContainer=false){
    如果(root.id==groundntid&&foundContainer)返回true;//在容器中找到它
    如果(root.id==子代id&&!foundContainer)返回false;//我们在容器之前找到了子代
    //反复出现在孩子们身上
    const newFoundContainer=foundContainer | | root.id==containerId;
    const childResults=root.children.map(
    child=>Isthis子代(子代ID、容器ID、子代、纽芬兰容器)
    );
    return或(childResults);//如果有子项命中,则返回true
    }
    //如果数组中的任何项为true,则返回true
    函数或(值){
    返回布尔值(value.filter(Boolean).length);
    }
    console.log(Isthis后代(7,1))//真的
    console.log(Isthis后代(1,7))//假的
    console.log(Isthis后代(7,3))//假的
    
    log(Isthis后代(3,2))//true
    此问题涉及一个常见问题:在树“类似”结构中查找节点。这总是涉及递归

    您可以编写一个函数
    isdescentant(rootObj、valueA、valueB)
    。它看起来像这样:

    function isDescendant(rootObj, parentId, childId) {
      const parentNode = findChildren(rootObj, parentId); // Find the parent node
      if (!parentNode) return false;
      return !!findChildren(parentNode, childId); // Find the child node
    }
    
    function findChildren(obj, id) {
      if (obj.id === id) return obj;
      if (obj.children) return obj.children.find(c => findChildren(c, id));
    }
    

    可能有点过于冗长,但有了一些输入参数,您可以这样做

    函数findNodeById(分支,id){
    如果(!分支){
    返回null;
    }
    if(branch.id==id){
    返回分支;
    }
    for(让分支的子对象。子对象){
    让结果=findNodeById(子项,id);
    如果(结果){
    返回结果;
    }
    }
    返回null;
    }
    函数是其子代(树、子ID、父ID){
    const parent=findNodeById(树,parentId);
    如果(!父项){
    返回false;
    }
    const child=findNodeById(父,子ID);
    返回子项!==null;
    }
    常数分支={
    儿童:[
    {
    名称:‘a’,
    id:1,
    儿童:[
    {
    名称:‘b’,
    id:2,
    儿童:[
    {
    名称:‘c’,
    id:3,
    儿童:[]
    },
    {
    姓名:'cc',
    id:4,
    儿童:[]
    }                       
    ]
    },
    {
    姓名:‘ba’,
    id:6,
    儿童:[
    {
    名称:‘c’,
    id:8,
    儿童:[]
    },
    {
    名称:“cd”,
    id:7,
    儿童:[]
    }                       
    ]
    }               
    ]
    },
    {
    名称:“bb”,
    id:10,
    儿童:[]
    }
    ]
    };
    log(Isthis后代(分支,7,1))//真的
    log(isThisDescendant(分支,1,7))//false
    log(Isthis子孙(分支,7,3))//false
    
    console.log(isThisDescendant(branch,3,2))//true
    您可以创建递归函数,该函数将在数组上使用
    forEach
    循环,还可以在看到第二个参数后检查第一个参数是否存在