简体   繁体   中英

How to modify tree object by property?

I have an object with type:

export interface TreeNode extends ITreeNode {
   name: string,
   children:  TreeNode[],
   show?: boolean;
}

I need to reduce this object by property show and return a new tree where show is true or undefined .

I have tried this:

  function prepareNodes(source: TreeNode) {
        if (source.show!== undefined || source.show == false) delete source;
      if (source.children) {
        source.children.forEach((child: TreeNode) => {
          this.prepareNodes(child);
        });
      }
  }

Also I tried:

function prepareNodes(source: any) {
      if (source.show !== undefined && source.show === false) source = null;
      if (source.children) {
        source.children = source.children.filter((child: any) => child.show== undefined || child.show === true);
        source.children.forEach((child: any) => prepareNodes(child));
      }
  }

Currently my assumption is that you want to produce a new tree containing just those nodes of the original tree where the show property is either true or undefined for that node and all ancestor nodes . So if show is false on any node, the output tree will not contain that node or any subtree of that node.

I also assume that it's possible for the root node to have show of false , in which case the whole tree might end up undefined . You can't set modify an object to become undefined ; you can change its contents, but you can't delete it. So I'm not going to present anything that tries to modify the original tree. I won't touch the original tree. Instead I will produce a completely new tree.

Here goes:

const defined = <T,>(x: T | undefined): x is T => typeof x !== "undefined";

function filterTree(source: TreeNode): TreeNode | undefined {
  if (source.show === false) return;
  return {
    name: source.name,
    show: source.show,
    children: source.children.map(filterTree).filter(defined)
  }
}

The filterTree() function will return undefined if the argument node's show property is exactly false (and not undefined ). Otherwise, it produces a new node with the same name and show , and whose children property is what you get when you call filterTree() (recursively) on each of the original node's children , and then filter out any undefined nodes.

I'm using a user-defined type guard function called defined to let the compiler know that the filter ing takes an array of TreeNode | undefined TreeNode | undefined and produces an array of TreeNode , eliminating any undefined entries.

Hopefully this meets your use cases; please test it out on whatever data you have and check, because the question unfortunately did not include such data.

Playground link to code

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