I am given a question as follows:
B = C, D
A = B
C = E
meaning B is dependent on variable C and D, while A is dependent on B, and so on. Variable E and D is independent.
Input of 'A' should then return:
E, C, D, B, A
listing all dependent variables. To solve this problem, I first started off by defining a dictionary to iterate this condition easily:
letter = {'A' : ['B'], 'B' : ['C', 'D'], 'C' : ['E']}
However, I am now stuck on how I should loop this in order to print all the children efficiently. I believe this is wrong but I think I may be going in the right direction:
def problem(value):
letter = {'A' : ['B'], 'B' : ['C', 'D'], 'C' : ['E']}
for i in letter:
if i != value:
continue
if len(letter[i]) > 1:
for k in letter:
print("".join(letter[k]), k)
print("".join(letter[i]), i)
Please help!
Stolen from http://code.activestate.com/recipes/576570-dependency-resolver/ after some quick googling.
def dep(arg):
'''
Dependency resolver
"arg" is a dependency dictionary in which
the values are the dependencies of their respective keys.
'''
d=dict((k, set(arg[k])) for k in arg)
r=[]
while d:
# values not in keys (items without dep)
t=set(i for v in d.values() for i in v)-set(d.keys())
# and keys without value (items without dep)
t.update(k for k, v in d.items() if not v)
# can be done right away
r.append(t)
# and cleaned up
d=dict(((k, v-t) for k, v in d.items() if v))
return r
if __name__=='__main__':
d=dict(
a=('b','c'),
b=('c','d'),
e=(),
f=('c','e'),
g=('h','f'),
i=('f',)
)
print dep(d)
You have a list inside of another list. Write a nested for loop inside of another for loop and then run that through your test logic. For the outer list iterate over every part of the inner list and then move to the next part of the outer list.
Related
Just started learning Python a month ago. I'm stumped on an issue.
Trying to update a dictionary using a for loop. I would like to store the variable using the for loop's variable name as key and the variable value as the dictionary's value. I'm trying to use % to make it a one liner. Here's what I have so far:
grbl_parser_d = {
'a': 'null', # Motion Mode
'b': 'null', # Coordinate System Select
'c': 'null' # Plane Select
}
grbl_out = [GC:G0 G54 G17]
def filtergrblparser():
global grbl_parser_d
for l, r in [grbl_out.strip('[]').split(':')]:
for a, b, c in [r.split(' ')]:
# grbl_parser_d.update({'%': x}) % x
grbl_parser_d.update({'a': a})
grbl_parser_d.update({'b': b})
grbl_parser_d.update({'c': c})
The 'grbl_out' variable is the output from an Arduino.
Trying to use something like: grbl_parser_d.update({'%': a}) % a.name
'a.name' would be the for loop's variable name, not the value. Is this even possible? Any other suggestions and tips to clean up the code would also be greatly appreciated. Thanks!
You don't need loops for this, and I wouldn't try to cram it onto one line. Here's a simple function that should do what you want.
def filtergrblparser(grbl_out):
l, r = grbl_out.strip('[]').split(':')
a, b, c = r.split(' ')
grbl_parser_d = {
'a': a, # Motion Mode
'b': b, # Coordinate System Select
'c': c # Plane Select
}
return grbl_parser_d
# I'm assuming you meant this to be a string
grbl_out = "[GC:G0 G54 G17]"
grbl_parser_d = filtergrblparser(grbl_out)
print(grbl_parser_d)
# {'a': 'G0', 'b': 'G54', 'c': 'G17'}
This is generally a bad idea, but it could be done with another for loop.
# it's not clear why you're throwing this in a list just to iterate once over it
l, r = grbl_out.strip('[]').split(':')
a, b, c = r.split(' ')
for k in ['a', 'b', 'c']:
grbl_parser_d[k] = vars()[k]
But really it looks like you're trying to do:
grbl_parser_d = dict(zip('abc', grbl_out.strip('[]').split(':')[1].split(' ')))
Which is probably best written as:
l, r = grbl_out.strip('[]').split(':')
grbl_parser_d = dict(zip('abc', r.split(' ')))
I'm trying to build a method where if an item is not in a dictionary then it uses the last member of a list and updates the dictionary accordingly. Sort of like a combination of the pop and setdefault method. What I tried was the following:
dict1 = {1:2,3:4,5:6}
b = 7
c = [8,9,10]
e = dict1.setdefault(b, {}).update(pop(c))
So I would like the output to be where {7:10} gets updated to dict1, that is to say, if b is not in the keys of dict1 then the code updates dict1 with an item using b and the last item of c.
It might be possible for you to abuse a defaultdict:
from collections import defaultdict
c = [8, 9, 10]
dict1 = defaultdict(c.pop, {1: 2, 3: 4, 5: 6})
b = 7
e = dict1[b]
This will pop an item from c and make it a value of dict1 whenever a key missing from dict1 is accessed. (That means the expression dict1[b] on its own has side-effects.) There are many situations where that behaviour is more confusing than helpful, though, in which case you can opt for explicitness:
if b in dict1:
e = dict1[b]
else:
e = dict1[b] = c.pop()
which can of course be wrapped up in a function:
def get_or_pop(mapping, key, source):
if key in mapping:
v = mapping[key]
else:
v = mapping[key] = source.pop()
return v
⋮
e = get_or_pop(dict1, b, c)
Considering your variables, you could use the following code snippet
dict1[b] = dict1.pop(b, c.pop())
where you are updating the dictionary "dict1" with the key "b" and the value c.pop(), (last value of the list in c, equivalent to c[-1] in this case). Note that this is possible because the key value b=7 is not in you original dictionary.
I have something like this:
class C:
def get_data(): returns a list
d = {several instances of C}
Now, how do I iterate over all elements of all lists? I failed miserably:
[e for e in [v.get_data() for _, v in d.items()]]
The inner loop will produce a list of lists which can not be digested by the outer loop.
You want a flatten:
[e for _, v in d.items() for e in v.get_data()]
Note the order of the loops.
import itertools
class C:
def get_data(self): return ['a','b']
d = {'a' : C(), 'b' : C()}
print [e for e in itertools.chain.from_iterable(v.get_data() for v in d.values())]
Will print
['a', 'b', 'a', 'b']
Just modify your existing expression -
[item for sublist in [v.get_data() for _, v in d.items()] for item in sublist]
#piokuc's answer is the better option, but in Python 3, yield from is a possibility:
class C:
def get_data(self):
return ['a','b']
def extract(dict_):
"""Yield elements from sublists."""
for _, v in dict_.items():
yield from v.get_data()
d = {'a' : C(), 'b' : C()}
[e for e in extract(d)]
# ['a', 'b', 'a', 'b']
Not sure what you mean by "iterate over all elements", but based on the code in your question, the following will create a list of all the elements in both Python 2 & 3 and doesn't require importing anything else:
class C:
def get_data(self): return ['a', 'b']
d = {'a' : C(), 'b' : C()}
print([e for c in d.values() for e in c.get_data()]) # -> ['a', 'b', 'a', 'b']
In Python 2 you might want to use d.itervalues() instead of d.values() because it creates an iterator of the values rather than creating a temporary list of them (which is what Python 3 does automatically when the values() method called).
I have an array of dictionary elements like this:
d = [{'k': 'k1', 'v':4}, {'k': 'k2', 'v':5}, {'k': 'k3', 'v':2}]
I would like to retrieve a value of 'k' from the the dictionary element with lowest 'v', there may be more than one with the same lowest value. In the case of the example above, I would like to get:
['k3']
This is what what I have so far, is this the most efficient and pythonic way of solving the problem (besides collapsing the two lines into one)?
m = min([x['v'] for x in d])
r = [x['k'] for x in d if x['v'] == m]
Thanks.
Remove the unnecessary list comprehension and use a generator expression instead.
m = min(x['v'] for x in d)
r = [x['k'] for x in d if x['v'] == m]
But is there a reason you are keeping a list of key-value pairs, rather than a dict? (To have a multimap?)
d = {'k1':4, 'k2':5, 'k3':2}
m = min(d.itervalues())
r = [k for k, v in d.iteritems() if v == m]
r = min(d, key=lambda x: x["v"])["k"]
This should give you 'k3'
I'm trying to get the key with the lowest value in a dictionary where the key is in a separate list. I also fear that initializing my variable "key" in the way I am might cause trouble in the future, even though I don't think it will.
d = { "a":3, "b":2, "c":7 }
l = ["a","b"]
key = l[0]
for c in l:
key = c if d[c] < d[key] else key
print key
I'm still trying to get a handle on list comprehension. I have tried something like this to replace the for loop and everything, but it didn't work:
key = c if d[c] < d[key] else key for c in l
Ended with an invalid syntax error.
Use the key parameter to the min() function to pick out a lowest key:
min(l, key=d.__getitem__)
The key parameter must be a callable that maps items in the input list to a value by which you want to pick the minimum item. In your example, 'b' is the lowest item because d maps it to 2, while 'a' is mapped to 3.
Demo:
>>> d = { "a":3, "b":2, "c":7 }
>>> l = ["a","b"]
>>> min(l, key=d.__getitem__)
'b'
If there is any value in l that is not listed in d, d.__getitem__ will raise a KeyError:
>>> min(['a', 'b', 'e'], key=d.__getitem__)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'e'
You could also use lambda i: d[i] to get the same effect without scary direct use of dunder (double-underscore) special methods.
If you want to ignore non-existent keys, use:
min(['a', 'b', 'e'], key=lambda i: d.get(i, float('inf'))
float('inf') is guaranteed to always be larger than any other number, so in the above example 'e' will not be considered a minimum because it doesn't exist in d.