Arithmetic operators on lists/tuples in Python? - python

I have a couple functions like this:
object obj.getChild(childIndex)
int obj.numChildren()
So I am using these to create this function:
collection obj.getChildren()
I am flexible in the return type, but I will doing a lot of "subtraction", "multiplication" using another list. So something like this:
children = obj.getChildren()
children = [5,10,15,20,25]
globalChildren = [1,2,3,4,5,6,7,8,9,10,12,14,16,18,20]
difference = children - globalChildren
difference = [15,25]
shared = children * globalChildren
shared = [5,10,20]
Is there a fast and elegant way to do these or do I have to go through each element one by one and gather the elements manually?

You're looking for sets
children = {5,10,15,20,25}
globalChildren = {1,2,3,4,5,6,7,8,9,10,12,14,16,18,20}
difference = children - globalChildren
shared = children & globalChildren

Related

Sum of all Nodes Iteratively - Not Recursively - Without 'left' and 'right'

I have this Binary Tree Structure:
# A Node is an object
# - value : Number
# - children : List of Nodes
class Node:
def __init__(self, value, children):
self.value = value
self.children = children
I can easily sum the Nodes, recursively:
def sumNodesRec(root):
sumOfNodes = 0
for child in root.children:
sumOfNodes += sumNodesRec(child)
return root.value + sumOfNodes
Example Tree:
exampleTree = Node(1,[Node(2,[]),Node(3,[Node(4,[Node(5,[]),Node(6,[Node(7,[])])])])])
sumNodesRec(exampleTree)
> 28
However, I'm having difficulty figuring out how to sum all the nodes iteratively. Normally, with a binary tree that has 'left' and 'right' in the definition, I can find the sum. But, this definition is tripping me up a bit when thinking about it iteratively.
Any help or explanation would be great. I'm trying to make sure I'm not always doing things recursively, so I'm trying to practice creating normally recursive functions as iterative types, instead.
If we're talking iteration, this is a good use case for a queue.
total = 0
queue = [exampleTree]
while queue:
v = queue.pop(0)
queue.extend(v.children)
total += v.value
print(total)
28
This is a common idiom. Iterative graph traversal algorithms also work in this manner.
You can simulate stacks/queues using python's vanilla lists. Other (better) alternatives would be the collections.deque structure in the standard library. I should explicitly mention that its enque/deque operations are more efficient than what you'd expect from a vanilla list.
Iteratively you can create a list, stack, queue, or other structure that can hold the items you run through. Put the root into it. Start going through the list, take an element and add its children into the list also. Add the value to the sum. Take next element and repeat. This way there’s no recursion but performance and memory usage may be worse.
In response to the first answer:
def sumNodes(root):
current = [root]
nodeList = []
while current:
next_level = []
for n in current:
nodeList.append(n.value)
next_level.extend(n.children)
current = next_level
return sum(nodeList)
Thank you! That explanation helped me think through it more clearly.

Construct a Tree with list of Objects in Python

I created a class that is formatted as follows:
class PathStructure(object):
def __init__(self, Description, ID, Parent):
self.Description = Description
self.ID = ID
self.Parent = Parent
self.Children = []
Where Description, ID and Parent are strings, and Children are lists of PathStructure objects; thus, I know all the parent-child relationships. I want to be able to construct a graphical representation of this tree, so each PathStructure object becomes a node with the parent-child relationships linking the nodes. Creating the nodes is easy, I think:
nodes = {}
For item in pathstructure_list:
name = item.Description
nodes[name] = item
I am having trouble thinking of a way to link these nodes into create a tree structure out of the linked nodes. I have looked at examples, but I am kind of new to using dicts, so I don't really understand the solutions -- especially since I will be constructing a dict of objects.
EDIT:
To clarify, I initialize each PathStructure object from a spreadsheet of information, and then I determine the parent-child relationships. For example:
first = PathStructure('Master','1-234-5',None)
second = PathStructure('Sub One','2-345-6',first.ID)
third = PathStructure('Sub Two','3-456-7',first.ID)
fourth = PathStructure('Sub Three','4-597-8',second.ID)
pathstructs = [first, second, third, fourth]
And then I determine each object's children through a function, so I know each object's parent and child.
I was able to get close to where I want to be with the following:
full = collections.defaultdict(dict)
for item in pathstructs:
name = item.Description
ident = item.ID
perent = item.Parent
final = full[ident]
if parent:
full[parent][ident] = final
else:
root = final
But this method gets rid of the PathStructure objects, so I am stuck with a tree of string instead of object.

SQLAlchemy: how to select if in one list or another list?

I have a class which looks something like this:
class A(Base):
__tablename__ = "a";
id = Column(Integer, primary_key=True)
stuff = relationship('Stuff', secondary=stuff_a)
more_stuff = relationship('Stuff', secondary=more_stuff_a)
Basically two lists, stuff and more_stuff containing lists of Stuff.
I want to do a query which selects all A which have Stuff with id=X in either stuff list or in more_stuff list.
This is how I would do it for one list:
session.query(A).join(Stuff).filter(Stuff.id==X)
But that won't pick up Stuff from more_stuff.
I think that if you have two relationships from A to Stuff, even when you join for one, you need to explicitly specify which one, or sqlalchemy will rightfully complain. You can do this as follows:
q = (
session
.query(A)
.join(Stuff, A.stuff) # #note: here you specify the relationship
.filter(Stuff.id == X)
)
As to filter for both lists, you need to use an or_ operator in a filter. In order to be able to reference to both relationships, the easiest is to create aliases (give different names) to each of them. Then the code looks like below:
S1 = aliased(Stuff)
S2 = aliased(Stuff)
q = (
session
.query(A)
.join(S1, A.stuff) # S1 will refer to `A.stuff`
.join(S2, A.more_stuff) # S2 will refer to `A.more_stuff`
.filter(or_(S1.id == X, S2.id == X))
)
Alternatively, a cleaner code can be achieved with relationship.any():
q = (
session
.query(A)
.filter(or_(
A.stuff.any(Stuff.id == X), # here Stuff will refer to `A.stuff`
A.more_stuff.any(Stuff.id == X), # here Stuff will refer to `A.more_stuff`
))
)
but you will need to compare performance difference between two versions as the latter is implemented using EXISTS with sub-selects.

py2neo - How can I use merge_one function along with multiple attributes for my node?

I have overcome the problem of avoiding the creation of duplicate nodes on my DB with the use of merge_one functions which works like that:
t=graph.merge_one("User","ID","someID")
which creates the node with unique ID. My problem is that I can't find a way to add multiple attributes/properties to my node along with the ID which is added automatically (date for example).
I have managed to achieve this the old "duplicate" way but it doesn't work now since merge_one can't accept more arguments! Any ideas???
Graph.merge_one only allows you to specify one key-value pair because it's meant to be used with a uniqueness constraint on a node label and property. Is there anything wrong with finding the node by its unique id with merge_one and then setting the properties?
t = graph.merge_one("User", "ID", "someID")
t['name'] = 'Nicole'
t['age'] = 23
t.push()
I know I am a bit late... but still useful I think
Using py2neo==2.0.7 and the docs (about Node.properties):
... and the latter is an instance of PropertySet which extends dict.
So the following worked for me:
m = graph.merge_one("Model", "mid", MID_SR)
m.properties.update({
'vendor':"XX",
'model':"XYZ",
'software':"OS",
'modelVersion':"",
'hardware':"",
'softwareVesion':"12.06"
})
graph.push(m)
This hacky function will iterate through the properties and values and labels gradually eliminating all nodes that don't match each criteria submitted. The final result will be a list of all (if any) nodes that match all the properties and labels supplied.
def find_multiProp(graph, *labels, **properties):
results = None
for l in labels:
for k,v in properties.iteritems():
if results == None:
genNodes = lambda l,k,v: graph.find(l, property_key=k, property_value=v)
results = [r for r in genNodes(l,k,v)]
continue
prevResults = results
results = [n for n in genNodes(l,k,v) if n in prevResults]
return results
The final result can be used to assess uniqueness and (if empty) create a new node, by combining the two functions together...
def merge_one_multiProp(graph, *labels, **properties):
r = find_multiProp(graph, *labels, **properties)
if not r:
# remove tuple association
node,= graph.create(Node(*labels, **properties))
else:
node = r[0]
return node
example...
from py2neo import Node, Graph
graph = Graph()
properties = {'p1':'v1', 'p2':'v2'}
labels = ('label1', 'label2')
graph.create(Node(*labels, **properties))
for l in labels:
graph.create(Node(l, **properties))
graph.create(Node(*labels, p1='v1'))
node = merge_one_multiProp(graph, *labels, **properties)

Hierarchical queries on datastore

I am trying to create hierarchical queries on the App Engine.
My datastore have parents and children. Each parent has children. Imagine that I have to find children. I have a condition on the parent and an other on the children for example, imagine a real family datastore, my conditions are: I want all children that are a boy from parent who are 35 years old or more.
The query I have for now is something like:
P = Parent.query(Parent.age >= 35)
for p in P:
C = Children.query(gender == "boy", ancestor = p.key)
for c in C:
-> here I print information on the children
But the query is very slow with a lot of parent and children to test. I want to avoid iteration like for etc. because I think it take a long time because of that! What is the best practice to have his kind of query but quickly?
I have also brothers for the children and I can make queries, for example if I want all children that have parent that are more that 35 yers old and a sister named "Sisi", I will have (each children have his brothers on the value "brother"):
P = Parent.query(Parent.age >= 35)
for p in P:
C = Children.query(gender == "girl", name == "Sisi", ancestor = p.key)
for c in C:
C1 = Children.query(gender == "boy", brother == c.key, ancestor = p.key)
for c1 in C1:
->Here I print information about the children
In fact this example (family example) good for my project but it give an idea of the problem I have
How I've been able to do this before is to store the keys in a separate lookup entity. This goes along the key-value store premise that duplicate info is sometimes necessary for faster lookups. For example:
ParentChildLookup
- parent_key = ndb.KeyProperty()
- child_key = ndb.KeyProperty()
You could even add a third dimension of you are getting grandchildren:
ParentChildLookup
- parent_key = ndb.KeyProperty()
- child_key = ndb.KeyProperty()
- grandchildren_key = ndb.KeyProperty()
If you wanted to look everything up in a single query, you can add the repeated clause to make children and grandchildren a list:
ParentChildLookup
- parent_key = ndb.KeyProperty()
- child_key = ndb.KeyProperty(repeated=True)
- grandchildren_key = ndb.KeyProperty(repeated=True)
You then need to insert/update these lookup values anytime there's a change in relationships. The benefit of this is that you can avoid a lot of queries, specifically nested or multi-property queries. If you don't like this approach, I would recommend taking a look at the "Relationship Model" explanation here: https://cloud.google.com/appengine/articles/modeling. You can store the relationships between many-to-many objects without the need to store them all in the same entity.

Categories

Resources