Basically I have a list of key:items in a dictionary, and I am using a loop to find the key that matches the item I get, and I have functions for every key. The keys are numbered though, so I need to take off the last number.
This leaves me with needing to call a function from a string like the one in the subject:
key[-1]()
key[-1] actually is a string that returns something like scalcs, and that is the name of a function of mine that I then need to call.
I've searched around and have seen stuff about classes. I'm new and honestly have never worked with classes at all and have a lot of code and a lot of these functions. I would rather not do that method if at all possible.
d = {key1: item1, key2: item2, akey1: item3, akey2: item4, dkey1: item1, dkey2: item2}
I want to call key, akey, or dkey when my value matches that of the value attached to the key in the dictionary.
So I will loop through d like this:
for key, value in d.items():
if id == value:
print key[:-1]
Now I just need to call that key[:-1]
def hello_world():
print "hello world"
d = {'hello':hello_world}
d['hello']()
locals()['hello_world']()
I'm not entirely sure that I understand your question. Is the following right?
You have dictionaries
d1 = {key1: item1, key2: item2, ...}
and
d2 = {key1: function1, key2: function2, ...}
Given an item item2, you want to find function2.
If that's it, then you should store the information you have differently, in the form
d = {item1: function1, item2: function2, ...}
The function you want is then d[item2].
To generate d from d1 and d2, you can do
d = {item: d2[key] for key, item in d1.items()}
Instead of storing the name of your function as key of your dictionary, you could try to store the function itself:
>>> f = lambda x:x+1
>>> g = lambda x:x-1
>>> D = {f:'0', g:'1'}
>>> (F,) = [k for k,v in D.items() if v=="0"]
>>> F(3)
4
If you need to keep your keys as strings, then create a second dictionary (key_as_string, corresponding_function) with all the correspondences and just retrieve the function corresponding to the key you got at the previous step.
Note that you need to be very careful that you don't have multiple keys with the same value, otherwise, there's no telling that you'll get a unique function. The safest way would be to build a reverse dictionary of what you have: (some_string_index, a_function).
Note also that the function is just an object: in the example above, I used something very simple like a lambda, but you could use something far more complicated:
def a_function(...):
...
your_dictionary = {a_function: your_index}
safer_dictionary = {your_index: a_function}
Related
I am trying to find a way to return more than one result for my dictionary in Python:
def transitive_property(d1, d2):
'''
Return a new dictionary in which the keys are from d1 and the values are from d2.
A key-value pair should be included only if the value associated with a key in d1
is a key in d2.
>>> transitive_property({'one':1, 'two':2}, {1:1.0})
{'one':1.0}
>>> transitive_property({'one':1, 'two':2}, {3:3.0})
{}
>>> transitive_property({'one':1, 'two':2, 'three':3}, {1:1.0, 3:3.0})
{'one':1.0}
{'three': 3.0}
'''
for key, val in d1.items():
if val in d2:
return {key:d2[val]}
else:
return {}
I've come up with a bunch of different things but they would never pass a few test cases such as the third one (with {'three':3}). This what results when I test using the third case in the doc string:
{'one':1.0}
So since it doesn't return {'three':3.0}, I feel that it only returns a single occurrence within the dictionary, so maybe it's a matter of returning a new dictionary so it could iterate over all of the cases. What would you say on this approach? I'm quite new so I hope the code below makes some sense despite the syntax errors. I really did try.
empty = {}
for key, val in d1.items():
if val in d2:
return empty += key, d2[val]
return empty
Your idea almost works but (i) you are returning the value immediately, which exits the function at that point, and (ii) you can't add properties to a dictionary using +=. Instead you need to set its properties using dictionary[key] = value.
result = {}
for key, val in d1.items():
if val in d2:
result[key] = d2[val]
return result
This can also be written more succinctly as a dictionary comprehension:
def transitive_property(d1, d2):
return {key: d2[val] for key, val in d1.items() if val in d2}
You can also have the function return a list of dictionaries with a single key-value pair in each, though I'm not sure why you would want that:
def transitive_property(d1, d2):
return [{key: d2[val]} for key, val in d1.items() if val in d2]
If return is used to , then the function is terminated for that particular call . So if you want to return more than one value it is impossible. You can use arrays instead .You can store values in array and the return thhe array.
I have a dictionary like this :
d = {'v03':["elem_A","elem_B","elem_C"],'v02':["elem_A","elem_D","elem_C"],'v01':["elem_A","elem_E"]}
How would you return a new dictionary with the elements that are not contained in the key of the highest value ?
In this case :
d2 = {'v02':['elem_D'],'v01':["elem_E"]}
Thank you,
I prefer to do differences with the builtin data type designed for it: sets.
It is also preferable to write loops rather than elaborate comprehensions. One-liners are clever, but understandable code that you can return to and understand is even better.
d = {'v03':["elem_A","elem_B","elem_C"],'v02':["elem_A","elem_D","elem_C"],'v01':["elem_A","elem_E"]}
last = None
d2 = {}
for key in sorted(d.keys()):
if last:
if set(d[last]) - set(d[key]):
d2[last] = sorted(set(d[last]) - set(d[key]))
last = key
print d2
{'v01': ['elem_E'], 'v02': ['elem_D']}
from collections import defaultdict
myNewDict = defaultdict(list)
all_keys = d.keys()
all_keys.sort()
max_value = all_keys[-1]
for key in d:
if key != max_value:
for value in d[key]:
if value not in d[max_value]:
myNewDict[key].append(value)
You can get fancier with set operations by taking the set difference between the values in d[max_value] and each of the other keys but first I think you should get comfortable working with dictionaries and lists.
defaultdict(<type 'list'>, {'v01': ['elem_E'], 'v02': ['elem_D']})
one reason not to use sets is that the solution does not generalize enough because sets can only have hashable objects. If your values are lists of lists the members (sublists) are not hashable so you can't use a set operation
Depending on your python version, you may be able to get this done with only one line, using dict comprehension:
>>> d2 = {k:[v for v in values if not v in d.get(max(d.keys()))] for k, values in d.items()}
>>> d2
{'v01': ['elem_E'], 'v02': ['elem_D'], 'v03': []}
This puts together a copy of dict d with containing lists being stripped off all items stored at the max key. The resulting dict looks more or less like what you are going for.
If you don't want the empty list at key v03, wrap the result itself in another dict:
>>> {k:v for k,v in d2.items() if len(v) > 0}
{'v01': ['elem_E'], 'v02': ['elem_D']}
EDIT:
In case your original dict has a very large keyset [or said operation is required frequently], you might also want to substitute the expression d.get(max(d.keys())) by some previously assigned list variable for performance [but I ain't sure if it doesn't in fact get pre-computed anyway]. This speeds up the whole thing by almost 100%. The following runs 100,000 times in 1.5 secs on my machine, whereas the unsubstituted expression takes more than 3 seconds.
>>> bl = d.get(max(d.keys()))
>>> d2 = {k:v for k,v in {k:[v for v in values if not v in bl] for k, values in d.items()}.items() if len(v) > 0}
This is a question relative to the solution provided here, it involves the following code as solution:
from collections import MutableMapping
def set_value(d, keys, newkey, newvalue, default_factory=dict):
"""
Equivalent to `reduce(dict.get, keys, d)[newkey] = newvalue`
if all `keys` exists and corresponding values are of correct type
"""
for key in keys:
try:
val = d[key]
except KeyError:
val = d[key] = default_factory()
else:
if not isinstance(val, MutableMapping):
val = d[key] = default_factory()
d = val
d[newkey] = newvalue
I'm hoping someone could provide me some explanation why this code works. I'm confused how the passed in dict 'd' doesn't get constantly overwritten where d = val. How does the dict 'd' keep getting further nested dictionaries without ever indexing to the next node? Sorry, if that doesn't make sense, i don't understand how this works.
Thanks for your help!
d is rebound; the variable is updated to point to val in each loop.
For each key in keys, either the key is found (val = d[key] succeeds) or the default_factory() is used to create a new value for that key.
If the key was found but the value was not a MutableMapping type, the found value is replaced with a new default_factory() result.
Once the new value has been determined for this level, d is told to forget about the old dictionary and pointed to the new instead.
Rebinding does not change the old value. It merely stops referring to that old value.
Let's use a simple example:
>>> d = {'foo': {}}
>>> keys = ['foo']
>>> newkey = 'bar'
>>> newval = 'eggs'
>>> original = d
At the start, original and d are the same object. Think of names here as paper labels, and their values as balloons. The labels are tied with string to the balloons. In the above example, the d and original labels are both tied to the same dictionary balloon.
When we enter the for key in keys loop, the d[key] lookup succeeds and val is tied to the result of d['foo'], an empty dictionary:
>>> key = keys[0]
>>> key
'foo'
>>> val = d[key]
>>> val
{}
This is a regular Python dictionary, and isinstance(val, MutableMapping) is True. Next line rebinds the d label to that dictionary. The string is simply untied from the original dictionary and now attached to the same balloon val is tied to:
>>> d = val
>>> d
{}
>>> original
{'foo': {}}
>>> d is val
True
>>> d is original
False
The original dictionary was not altered by the rebinding!
Having run out of keys (there was only one in keys), the next part then assigns newval to d[newkey]:
>>> d[newkey] = newval
>>> d
{'bar': 'eggs'}
However, d is not the only label attached to this dictionary balloon. Dictionaries themselves contain keys and values, both of which are labels that are tied to balloons too! The original label is still tied to the outer dictionary balloon, and it has a foo key associated value, which was tied to a nested dictionary, and it is this nested dictionary we just changed:
>>> original
{'foo': {'bar': 'eggs'}}
The algorithm merely followed along labels via strings to new dictionaries.
Using more complex key combinations just means more strings are being followed, with perhaps an extra dictionary being pumped up to be tied in.
I think your question boils down to:
Why does d[newkey] = newvalue modify the object, while d = var does not do anything to the object?
It is just the case that in Python, you can modify a mutable object in a function, but you can't change what object the outer name refers to.
I have a dictionary that looks like:
myD={'key_0':[[['descrp_0_0'],Obj_0_0],.....,[['descrp_0_N'],obj_0_N]]
,.....,
'key_N':[[['descrp_N_0'],Obj_N_0],.....,[['descrp_N_N'],obj_N_N]]}
All objs are ndarrays of the same shape and have a function f() that returns an x which is a float i.e.:
obj_0_0.f() --> x_0_0
I want to extract a dictionary with the descrp and obj and their respective key where obj.f() (i.e. x) is minimum for the values in each key (at the myD scope of N keys would give N items in shape of [descrp,obj]):
The result must look something like:
resD = {'key_0':[[descrp_0_min],obj_0_min],
.....,
'key_N':[[descrp_N_min],obj_0_min]}
Something like:
minXs = [min([item[-1].f() for item in v]) for k,v in myD.iteritems()]
minObjs = [item for k,v in myD.iteritems() for item in v if item[-1].get_potential_energy() == minXs[myD.keys().index(k)]]
resultList = zip(myD.keys(),minObjs)
resultDict = dict()
for i in resultList:
resultDict[i[0]]=i[1]
Although it works but is rather cumbersome and I think there must be an easier way to do this. Or maybe I should use numpy.ndarray for this purpose?
I appreciate your help and comments.
If I've understood the structure of your data correctly, I think you can solve this with a dictionary comprehension that calls the builtin min function and gives it a key function.
results = {key: min(values, key=lambda x:x[-1].f())
for key, values in myD.iteritems()}
Your code was really close already!
Let's say that I have a Python dictionary, but the values are a tuple:
E.g.
dict = {"Key1": (ValX1, ValY1, ValZ1), "Key2": (ValX2, ValY2, ValZ2),...,"Key99": (ValX99, ValY99, ValY99)}
and I want to retrieve only the third value from the tuple, eg. ValZ1, ValZ2, or ValZ99 from the example above.
I could do so using .iteritems(), for instance as:
for key, val in dict.iteritems():
ValZ = val[2]
however, is there a more direct approach?
Ideally, I'd like to query the dictionary by key and return only the third value in the tuple...
e.g.
dict[Key1] = ValZ1 instead of what I currently get, which is dict[Key1] = (ValX1, ValY1, ValZ1) which is not callable...
Any advice?
Just keep indexing:
>>> D = {"Key1": (1,2,3), "Key2": (4,5,6)}
>>> D["Key2"][2]
6
Use tuple unpacking:
for key, (valX, valY, valZ) in dict.iteritems():
...
Often people use
for key, (_, _, valZ) in dict.iteritems():
...
if they are only interested in one item of the tuple. But this may cause problem if you use the gettext module for multi language applications, as this model sets a global function called _.
As tuples are immutable, you are not able to set only one item like
d[key][0] = x
You have to unpack first:
x, y, z = d[key]
d[key] = x, newy, z
Using a generator expression!
for val in (x[2] for x in dict):
print val
You don't need to use iteritems because you're only looking at the values.