简体   繁体   中英

Pruning a tree by mapping nodes of tree that fail a test to its children

My problem here builds upon another problem I was trying to solve and received an excellent answer for where I have a tree:

const treeData = [{
  title: '0-0',
  key: '0-0',
  children: [{
    title: '0-0-0',
    key: '0-0-0',
    children: [
      { title: '0-0-0-0', key: '0-0-0-0', children: [] },
      { title: '0-0-0-1', key: '0-0-0-1', children: [] },
      { title: '0-0-0-2', key: '0-0-0-2', children: [] },
    ],
  }, {
    title: '0-0-1',
    key: '0-0-1',
    children: [
      { title: '0-0-1-0', key: '0-0-1-0', children: [] },
      { title: '0-0-1-1', key: '0-0-1-1', children: [] },
      { title: '0-0-1-2', key: '0-0-1-2', children: [] },
    ],
  }, {
    title: '0-0-2',
    key: '0-0-2',
    children: []
  }],
}, {
  title: '0-1',
  key: '0-1',
  children: [
    { title: '0-1-0-0', key: '0-1-0-0', children: [] },
    { title: '0-1-0-1', key: '0-1-0-1', children: [] },
    { title: '0-1-0-2', key: '0-1-0-2', children: [] },
  ],
}, {
  title: '0-2',
  key: '0-2',
  children: []
}];

and an array of leaf nodes:

const leafNodes = ['0-0-1-2', '0-1-0-1', '0-1-0-2']

Before, I just wanted a filtered/pruned copy of the tree that contains all the paths to the leaf nodes, but now I would like to further prune it by removing the parent node that doesn't satisfy a test -- the test being having all of its children included in the list of leaf nodes. The resulting tree would look like this:

const pruned = [{
    title: '0-0-1-2',
    key: '0-0-1-2',
    children: []
  },
  {
    title: '0-1-0-1',
    key: '0-1-0-1',
    children: []
  }, {
    title: '0-1-0-2',
    key: '0-1-0-2',
    children: []
  }
]

Here, the node with keys 0-0-1 would be removed because only one of its 3 child nodes ( 0-0-1-2 ) is included in the leafNodes list and the child nodes included in the leaf nodes list (in this case, just the one) are bumped up to the level of their now removed parent. This would flow back up to the parent of the removed node, now with key 0-0 , since not all of its children are included in the pruned tree.

This same pattern would apply to 0-1 .

You could iterate the array and check if the child are complete selected , then get the actual node or just some children, then take the children only.

 function getShort(array, keys) { var result = [], every = true; array.forEach(o => { var children; if (keys.includes(o.key)) return result.push(o); if (!o.children || !o.children.length) return every = false; children = getShort(o.children, keys); if (children.length && children.length === o.children.length) return result.push(o); result.push(...children); every = false; }); return every ? array : result; } const treeData = [{ key: '0-0', children: [{ key: '0-0-0', children: [{ key: '0-0-0-0', children: [] }, { key: '0-0-0-1', children: [] }, { key: '0-0-0-2', children: [] }] }, { key: '0-0-1', children: [{ key: '0-0-1-0', children: [] }, { key: '0-0-1-1', children: [] }, { key: '0-0-1-2', children: [] }] }, { key: '0-0-2', children: [] }] }, { key: '0-1', children: [{ key: '0-1-0-0', children: [] }, { key: '0-1-0-1', children: [] }, { key: '0-1-0-2', children: [] }] }, { key: '0-2', children: [] }], leafNodes = [ '0-0-0-0', '0-0-0-1', '0-0-0-2', // all 0-0-0 all 0-0 '0-0-1-0', '0-0-1-1', '0-0-1-2', // all 0-0-1 all 0-0 '0-0-2', // all 0-0-2 all 0-0 '0-1-0-1', '0-1-0-2' ], short = getShort(treeData, leafNodes); console.log(short);
 .as-console-wrapper { max-height: 100% !important; top: 0; }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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