简体   繁体   English

在给定条件下修改 JavaScript 中的树结构数据?

[英]Modifying tree structured data in JavaScript with given condition?

I have a tree data like this:我有这样的树数据:

var tree = [
  {
    id:"11",
    text: "Parent 1",
    type:"Parent",
    nodeSelected:false,
    nodes: [
      {
        text: "Child 1",
        parentId: "11",
        id:"21",
        nodeSelected:false,
        type: "Child",
        nodes: [
          {
            id:"36",
            text: "Grandchild 1",
            parentId: "21",
            nodeSelected:false,
            nodes:[],
            type: "Grandchild"
          },
          {
            id:"38",
            text: "Grandchild 2",
            parentId: "21",
            nodes:[],
            nodeSelected:false,
            type: "Grandchild"
          }
        ]
      },
      {
        id:"43",
        text: "Child 2",
        nodeSelected:false,
        parentId:"11",
        type: "Child",
        nodes: [
            {
            id:"52",
            parentId:"43",
            text: "Grandchild 1 of child 2",
            nodeSelected:false,
            nodes:[],
            type: "Grandchild"
          }
        ]
      }
    ]
  },
  {
    id:"46",
    text: "Parent 2",
    nodeSelected:false,
    type: "Parent",
    nodes:[]
  },
  {
    id:"48",
    text: "Parent 3",
    nodeSelected:false,
    type: "Parent",
    node:  [
        {
            id:"70",
            text: "child 3",
            parentId: "48",
            type: "Child",
            nodeSelected:false,
            nodes:[]
        }
    ]
  }
];

All of the nodeSelected are false.所有的nodeSelected都是假的。

I have group of Ids in form of an array.我有一组数组形式的 ID。

groupedIds=["11","21","43","52","48"];

I want to do nodeSelected property true based on groupId array with some condition.我想根据groupId array在某些条件下执行nodeSelected属性 true 。

the condition is such that if a parentId is mentioned along with its children ids then nodeSelected property of parent should remain false and child's nodeSelected should be true (and its nodes nodeSelected should also be 'true').条件是这样的,如果一个 parentId 连同它的子 ID 一起被提及,那么 parent 的nodeSelected属性应该保持为 false 并且孩子的nodeSelected应该是 true(并且它的nodes nodeSelected也应该是'true')。 Or else whole parent nodes nodeSelected should be true(along with it nodes).否则整个父节点nodeSelected应该是 true(连同它的节点)。

So the result will be like this:所以结果会是这样的:

var resultArray = [
  {
    id:"11",
    text: "Parent 1",
    type:"Parent",
    nodeSelected:false,
    nodes: [
      {
        text: "Child 1",
        parentId: "11",
        id:"21",
        nodeSelected:true,
        type: "Child",
        nodes: [
          {
            id:"36",
            text: "Grandchild 1",
            parentId: "21",
            nodeSelected:true,  
            type: "Grandchild"
          },
          {
            id:"38",
            text: "Grandchild 2",
            parentId: "21",
            nodeSelected:true,
            type: "Grandchild"
          }
        ]
      },
      {
        id:"43",
        text: "Child 2",
        nodeSelected:false,
        parentId:"11",
        type: "Child",
        nodes: [
            {
            id:"52",
            parentId:"43",
            text: "Grandchild 1 of child 2",
            nodeSelected:true,
            type: "Grandchild"
          }
        ]
      }
    ]
  },
  {
    id:"46",
    text: "Parent 2",
    nodeSelected:false,
    type: "Parent"
  },
  {
    id:"48",
    text: "Parent 3",
    nodeSelected:true,
    type: "Parent",
    node:  [
        {
            id:"70",
            text: "child 3",
            parentId: "48",
            type: "Child",
            nodeSelected:true
        }
    ]
  }
];

( My try ) Although incomplete but something like this we can do 我的尝试)虽然不完整但我们可以做这样的事情

tree.forEach((Parent) => {
            if (groupedIds.includes(Parent.id)) {
                let isSomeChildSelected = Parent.nodes.some((loc) => groupedIds.includes(loc.id));
                if (isSomeChildSelected) {
                    Parent.nodes.forEach((child) => {
                        if (groupedIds.includes(child.id)) {
                            let isSomeGrandChildSelected = child.nodes.some((grandchild) => groupedIds.includes(grandchild.id));
                            if (isSomeGrandChildSelected) {
                                child.nodes.forEach((grandchild) => {
                                    if (groupedIds.includes(grandchild.id)) {
                                        grandchild.isSelected = true;
                                    }
                                })
                            } else {
                                child.isSelected = true;
                                child.nodes.forEach((grandchild) => {
                                    grandchild.isSelected = true;
                                })
                            }
                        }
                    })
                } else {
                    Parent.isSelected = true;
                    Parent.nodes.forEach((child) => {
                        child.isSelected = true;
                        child.nodes.forEach((grandchild) => {
                            grandchild.isSelected = true;
                        })
                    })
                }
            }
        })

The above tried method solves the issue to some extent, but it is a bit complex.上面尝试的方法在一定程度上解决了这个问题,但是有点复杂。

Any help would be much appreciated.任何帮助将非常感激。 Thanks!谢谢!

I'm not going to do it for you (not out of malice, just because I'm not 100% sure I understand the question,).我不会为你做这件事(不是出于恶意,只是因为我不是 100% 确定我理解这个问题,)。 but I'll hopefully give you a big point in the right direction.但我希望能给你一个正确的方向。

When traversing trees, 90% of the time you need something called recursion.在遍历树时,90% 的时间你需要一种叫做递归的东西。 Recursion looks like this:递归看起来像这样:

function walk(items){
  items.forEach(items => {
    if(item.hasChildrenOrSomething){
      // notice the function calls itself:
      walk(item.children);
    }

    // Do something with item
  });
}

walk(tree);

There is one important thing to note here, which is that if you do some logic after calling the function inside itself, all the children of the current item will have that logic applied.这里有一件重要的事情要注意,如果你在调用 function执行一些逻辑,当前项的所有子项都将应用该逻辑。 So, here we go – in your case you want something like this:所以,我们在这里 go - 在你的情况下,你想要这样的东西:

const walk = (branch) => {
  branch.forEach(node => {
    // Check if this object even has children:
    if(node.hasOwnProperty('nodes') && node.nodes.length){
      walk(node.nodes);
      // Do your node.nodes.every check here
    }
    // Now check if this is in the array
  });
}

walk(tree);

If you've used recursion before, sorry, this whole post was probably just super patronising and has missed the point of your question.如果您以前使用过递归,对不起,整篇文章可能只是超级光顾,并且错过了您的问题的重点。 If you haven't, then can I just say I am a) jealous of you for getting to experience the feeling of something so elegant for the first time and b) sorry for you for having to unravel the mind boggling nature of them.如果你还没有,那么我只能说我 a) 嫉妒你第一次体验到如此优雅的感觉 b) 为你不得不解开它们令人难以置信的本质而感到抱歉。

This gives me output what I want(with recursion):这给了我 output 我想要的东西(递归):

 var tree = [ { id:"11", text: "Parent 1", type:"Parent", nodeSelected:false, nodes: [ { text: "Child 1", parentId: "11", id:"21", nodeSelected:false, type: "Child", nodes: [ { id:"36", text: "Grandchild 1", parentId: "21", nodeSelected:false, nodes:[], type: "Grandchild" }, { id:"38", text: "Grandchild 2", parentId: "21", nodes:[], nodeSelected:false, type: "Grandchild" } ] }, { id:"43", text: "Child 2", nodeSelected:false, parentId:"11", type: "Child", nodes: [ { id:"52", parentId:"43", text: "Grandchild 1 of child 2", nodeSelected:false, nodes:[], type: "Grandchild" } ] } ] }, { id:"46", text: "Parent 2", nodeSelected:false, type: "Parent", nodes:[] }, { id:"48", text: "Parent 3", nodeSelected:false, type: "Parent", nodes: [ { id:"70", text: "child 3", parentId: "48", type: "Child", nodeSelected:false, nodes:[] } ] } ]; groupedIds=["11","21","43","52","48"]; var selectAllNode=array=> array.forEach((value)=>{ value.nodeSelected=true; value.nodes? selectAllNode(value.nodes): [] }); var getFilteredData = array => array.forEach((ele)=>{ if(groupedIds.includes(ele.id)){ let isSomeSelected = ele.nodes.some((val)=>groupedIds.includes(val.id)); if(isSomeSelected){ getFilteredData(ele.nodes); } else { ele.nodeSelected=true; selectAllNode(ele.nodes); } } }); getFilteredData(tree); console.log(tree);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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