Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Copying trees #161

Open
elfring opened this issue Apr 2, 2021 · 1 comment
Open

Copying trees #161

elfring opened this issue Apr 2, 2021 · 1 comment

Comments

@elfring
Copy link

elfring commented Apr 2, 2021

I am looking for programming interfaces which support to copy trees while preserving referential integrity.
Further data processing can be performed with such copies.

@jannikmi
Copy link

The regular copy() and deepcopy() methods can be used for this.
In my custom node class i have added these functions:

def __copy__(self):
    return self.__class__(
        self.attributes,
    )

def __deepcopy__(self, memodict={}):
    """computes a deep copy of the sub-tree the node is a root of

    ATTENTION: this copy mechanism does only copy the instances from `self` downwards!
    -> call deepcopy(root_node) to copy a full tree
      """
      my_copy = copy(self)
      # recursion towards the leaves
      my_copy.children = [deepcopy(child) for child in self.children]
      return my_copy

It would however be cool if the nodes supported this by default.
With some additional functionality like node.copy_tree() which copies all nodes of the tree but then returns the copy of the node (not the root).

Perhaps this implementation of mine helps:

def copy_my_tree(self) -> "TreeNode":
    """computes a deep copy of the full tree the node belongs to

    Returns: the node corresponding to `self` in the copied tree
    """
    my_root = self.root
    my_root_copy = deepcopy(my_root)  # full copy of my tree
    # find copy of myself based on matching the some argument along the path
    # NOTE: more efficient than searching the whole tree
    matched_node = my_root_copy
    for node in self.path:  # walk down from the root
        if (
            node.is_root
        ):  # skip the first node in the path = root, has been matched already
            continue
        label2match = node.label
        matched_node = anytree.search.find(
            matched_node, lambda n: n.label == label2match
        )
    my_copy = matched_node
    return my_copy

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants