Listing all treeview nodes and children in a loop - python

I have a treeview that has parents and children.
I want to list the items, but can so far only list the parents.
This is my code:
i = 0
for x in tree_list:
for child in x.get_children(): # This works
print(x.item(child)["values"][1])
print("CHILD: ", child)
for baby in x.item(child).get_children(): # this doesn't work
print("baby for ", x, " is ", baby)
i = i + 1
The second part results in an error.
I am sure there is a way to do this, but I can't figure out how to get the child of each node.
Thanks,
Chris
I get this error
AttributeError: 'dict' object has no attribute 'get_children'
I expected a with all children in the list

Related

Create a Tree of Object Recursively (Python)

i would like to create a tree of objects called State.
Each State has a list of 4 robots and each states have differents robots coordinates.
The goal is to create a graph which will be solved by a Breadth First Search Algorithm.
(The original game is RicochetRobot maybe you guys know it).
class State:
def __init__(self,parent,childs,robots,cpt,):
self.parent = parent
self.childs = childs
self.robots = robots
self.cpt = cpt
I created a function create_child to do this
def create_child(self,depth):
#UP
#Depth is the tree height
if depth==0:
print("STOP")
return
else :
for i in range(4):
#Copying the robots of the current object
temp = copy.deepcopy(self.robots)
#Getting robot to move index
temp_robot = temp[i]
#removing this robot from the list
temp.pop(i)
#Moving up the robot and inserting it in the list
#Moving up is a simple function which increment the y of the robot
temp.insert(i,moving_up(temp_robot,create_board(init_robot())))
#Adding a new child into childs list
self.childs.append(State(self,self.childs,temp,self.cpt+1))
#Decrementing the depth
depth-=1
#Recursivity
for child in self.childs:
child.create_child(depth)
My problem is that when depth = 0 , it print STOP,but it doesnt return None, and the function keep going.
Anynone knows from where it come froms?
Also, if you can give advice on how to make my tree in an easier way it would be nice.
Alright so i think i found a solution , here it is :
depth = 1
parent = Initial_State
for j in range(depth):
for i in range(len(parent.childs)-1):
parent.childs[i].create_child()
parent = parent.childs[i]
It seems to be working. I dont use recursion anymore, i do it in a more iterative way and outside the function and it seems good.
Thank you

Search 3D list for single Item

I am creating a leaderboard creating system, where it checks if the Name is already in the Database, if not it adds it, and if it is it replaces the name and score.
import csv
winner =["Player", 100]
def leaderboardsave(winner):
fileCSV = open('scores.csv')
dataCSV = csv.reader(fileCSV)
playersScores = list(dataCSV)
winnerName = winner[0]
winner_index = playersScores.find(winnerName)
if winner_index > -1:
playersScores[winner_index] = winner
else:
playersScores.append(winner)
leaderboardsave(winner)
The CSV is saved like this:
Player, 20
Player2, 40
Player3, 30
Player4, 60
whenever I run
winner_index = playersScores.find(winnerName)
it returns "'list' object has no attribute 'find'"
Any other ways to find where the item is in the list? When i tried using .index, it wouldnt find it, i assume as it is looking for a list, not a single string?
You are getting that error because playerScores is a list object and a list object doesn't have a find function.
You can traverse a list to find a value by looping:
winner_index = [index for index, value in enumerate(playerScores) if value == winnerName]

Unexpected None in python print statement

I'm trying to print out a list of nodes connected to other nodes so I can view them for debugging some python code revolving around graphs. I'm doing this for practice so I'm setting up nodes/edges/groups myself.
I've tried printing out the connections with my function inside of the myNode class using a for each type loop. But I get different output if I specify the index of the array and call the same method on it.
def print_connections(self):
for node in self.connections:
print(node.name, end = " ")
...
for node in nodes:
node.print_connections()
print(" ") # so I can have a newline in between groups
print(nodes[1].print_connections())
The for/each has good output, or appears to be good:
2 5 3 0
which differs from the line with the indexed print:
2 5 3 0 None
Is this expected behavior in python? How can I get around this?
your print_connections(self) doesn't return any value, thus return None, and what you're trying to do is with print(nodes[1].print_connections()) is to print the returned value by nodes[1].print_connections(), which is going to be None,
so what you should do instead is just,
for node in nodes:
node.print_connections()
print(" ")
nodes[1].print_connections()

PyQt5 - try to build a gui with dynamic content

I would like to realize a gui to show fathers and their children. If you click on a child, it will be father and his children will fill the lables on the screen.
The family tree is an object "familytree". The Gui uses customized pyqt-classes. You could see below the initial screen.
I'm stuck with the evaluation of the signal.
def kinderInitialisieren(self):
# kinder
self.kinderName = [0 for kind in range(10)]
self.kinderNr = [0 for kind in range(10)]
for kind in range(10):
kinderLabel = TextFeld("Kind: ")
self.gestaltung.addWidget(kinderLabel, 1 + kind , 0)
self.kinderName[kind] = ButtonFeelsLikeLabel("Name")
self.gestaltung.addWidget(self.kinderName[kind], 1 + kind, 1)
self.kinderName[kind].pressed.connect( lambda n=kind: self.welcherKnopfGedrueckt(n))
Lambda-function delivers the index of the clicked button (I realized the names of children as buttons). But this index is like caged in the namespace of the class/function. For getting the children of person/button no.1 I've to access the object "family tree". How to break the namespace-prison?
GUI Family tree

Python Recursion through objects and child objects, Print child depth numbers

I have a simple class with an attribute that can contain a list of objects of the same class
class BoxItem:
def __init__(self, name, **kw):
self.name = name
self.boxItems = []
... #more attributes here
box1 = BoxItem('Normal Box')
box2 = BoxItem('Friendly Box')
box3 = BoxItem('Cool Box')
box4 = BoxItem('Big Box', [box1, box2]) #contains some children
example = BoxItem('Example Box', [box4,box3]) #contains another level of children
Working with our 'example' box object, I would like to maneuver through the depths of all possible box children it may have, and print out the objects formatted like so:
1 Example Box
1.1 Big Box
1.1.1 Normal Box
1.1.2 Friendly Box
1.2 Cool Box
The Tabbing between isn't needed, just wanting to show the tree format clearly. I am able to walk down the objects themselves and print out their titles, but I am not able to print out the front numbers that show the parent/child relationship. (1, 1.1, 1.2...)
Thanks in advance for your help :)
Edit
Here is what I have been working with so far
def print_boxes(box_list):
node_count = 0
for box in box_list:
node_count += 1
print str(node_count)+' '+box.name #prints out the root box
recursive_search(box,node_count)
def recursive_search(box,node_count): #recursive automatically
level = 0
for child in box.boxItems:
level += 1
for x in range(len(child.boxItems)):
print x+1 #this prints out some proper numbers
print "level: "+str(level) #experiment with level
print child.name #prints out child box name
recursive_search(child,node_count) #runs the function again inside the function
I think it might be more helpful to you if I post a working example of how to do this, as opposed to going through where you code is having problems. We might get to the point of understanding a lot faster that way. Your code has the correct idea that it needs to track the depth as it goes. But the only thing it is missing is a sense of nested depth (tree). It only knows the previous node_count, and then its current child count.
My example uses a closure to start the depth tracking object, and then creates an inner function to do the recursive part.
def recurse(box):
boxes = not isinstance(box, (list, tuple)) and [box] or box
depth = [1]
def wrapped(box):
depthStr = '.'.join([str(i) for i in depth])
print "%s %s" % (depthStr, box.name)
depth.append(1)
for child in box.boxItems:
wrapped(child)
depth[-1] += 1
depth.pop()
for box in boxes:
wrapped(box)
depth[0] += 1
Sample output from your examples:
>>> recurse(example)
1 Example Box
1.1 Big Box
1.1.1 Normal Box
1.1.2 Friendly Box
1.2 Cool Box
>>> recurse([example, example])
1 Example Box
1.1 Big Box
1.1.1 Normal Box
1.1.2 Friendly Box
1.2 Cool Box
2 Example Box
2.1 Big Box
2.1.1 Normal Box
2.1.2 Friendly Box
2.2 Cool Box
Breaking this down:
We first accept a box argument, and automatically convert it locally to a list, if you had only passed in a single box item. That way you can pass either one box objects, or a list/tuple of them.
depth is our depth tracker. Its a list of ints that we will build up and shrink down as the recursion happens. It starts at 1 for the first item / first level. Over time it can look like this: [1,1,2,3,1] depending on how deep it traverses. This is the major difference between my code and yours. Each recursion has access to this state.
Now we have this inner wrapped function. Its going to take a current box item and print it, and then iterate over its children. We get our print string by joining the current depth list, and then the name.
Every time we drop down into a child list, we add a starting level 1 to our depth list, and when we come out of that child loop, we pop it back off again. For every child in that loop, we increment that last item up.
Outside of that wrapped inner function, we then start the whole thing by looping over our initial boxes, calling wrapped and then incrementing our first level.
The inner wrapped function uses the depth list in a closure. I am willing to bet that others can offer some further improvements on this, but its what I came up with for an example.
Note about the args for the function
We could have also designed recurse to instead take a variable length argument list, instead of checking for a list. It would look like this (and would get rid of that first boxes = check):
def recurse(*boxes):
#boxes will always come in as a tuple no matter what
>>> recurse(example)
>>> recurse(example, example, example)
And if you originally start with a list of box items, you can pass it by doing:
>>> boxes = [example, example, example]
>>> recurse(*example) # this will unpack your list into args
You have two options:
Keep track of the additional information as an additional parameter in your recursion, e.g. myRecursiveFunction(..., ancestry=[])
Have each BoxItem keep track of its parent, whenever it is embedded in a BoxItem (in the __init__ constructor, set child.parent = self for each child). This is bad if you plan to have a BoxItem in more than one box.

Categories