object type attribute search fails
cli0 opened this issue · comments
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))