kayjan / bigtree

Tree Implementation and Methods for Python, integrated with list, dictionary, pandas and polars DataFrame.

Home Page:https://bigtree.readthedocs.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

object type attribute search fails

cli0 opened this issue · comments

commented

Hello, this library is amazing but I don't seem able to use functionalities available to nodes when the data assigned to the nodes are classes.

For example:

class Objects:
    def __init__(self,a,b):
        self.a = a
        self.b = b

    def get_b(self):
        return self.b

def test():
    root = Node("a", data=Objects({"nae":1,"surname":2},20))
    b = Node("b", data=Objects({"nae":1,"surname":2},3))
    c = Node("c", data=Objects({"nae":1,"surname":2},3))
    d = Node("d", data=Objects({"nae":1,"surname":2},3))

    root.children = [b, c, d]

    print(findall(root,lambda node: node.data.b))
    print(findall(root,lambda node: node.data.get_b()))

with results being
(Node(/a, data=<__main__.Objects object at 0x7fd4014274f0>), Node(/a/b, data=<__main__.Objects object at 0x7fd3e9d2d090>), Node(/a/c, data=<__main__.Objects object at 0x7fd3e9d2d5a0>), Node(/a/d, data=<__main__.Objects object at 0x7fd3e9d2d5d0>))

Or if I try

    print(find(root,lambda node: node.data.b > 2))

    raise SearchError(
bigtree.utils.exceptions.SearchError: Expected less than 1 element(s), found 4 elements
(Node(/a, data=<__main__.Objects object at 0x7f945e67b490>), Node(/a/b, data=<__main__.Objects object at 0x7f9446f910f0>), Node(/a/c, data=<__main__.Objects object at 0x7f9446f91600>), Node(/a/d, data=<__main__.Objects object at 0x7f9446f91630>))

How do I extract the actual value from my object?

Hello, thanks for using bigtree!

The output of findall is tuple of one or more nodes. The results being
(Node(/a, data=<__main__.Objects object at 0x7fd4014274f0>), Node(/a/b, data=<__main__.Objects object at 0x7fd3e9d2d090>), Node(/a/c, data=<__main__.Objects object at 0x7fd3e9d2d5a0>), Node(/a/d, data=<__main__.Objects object at 0x7fd3e9d2d5d0>))
is intended because it is returning a tuple of nodes. If you want to extract the values out, let me assume you want to extract the object variable a which is a dictionary, you can loop the results as such

nodes = findall(root, lambda node: node.data.b == 3)
print([node.data.a for node in nodes])
# [{'nae': 1, 'surname': 2}, {'nae': 1, 'surname': 2}, {'nae': 1, 'surname': 2}]

For your other point, the output of find is a single node, hence the criteria for find has to be unique. You can change the criteria to something more unique such as

print(find(root, lambda node: node.data.b == 20))
# Node(/a, data=<__main__.Objects object at 0x11a6eaf50>)

Alternatively, if you want your Objects class to be shown nicely instead of being shown as <__main__.Objects object at 0x7fd4014274f0>, you can modify your Objects class as such

class Objects:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def get_b(self):
        return self.b

    def __repr__(self):
        return f"Objects(a={self.a}, b={self.b})"


root = Node("a", data=Objects({"nae": 1, "surname": 2}, 20))
print(root)
# Node(/a, data=Objects(a={'nae': 1, 'surname': 2}, b=20))