I'm trying to assign the values of a nested dictionary to variables named after their key. I found this code on Stackoverflow but it only prints the key and value pair:
def myprint(d):
for k, v in d.items():
if isinstance(v, dict):
myprint(v)
else:
print("{0} : {1}".format(k, v))
I would like it so that for example, if I have the following in my dictionary: {thisIsADummy : 37}
I can somehow create a variable named thisIsADummy, named after the key, with the value 37
So my input ould be print(thisIsADummy) and the output would be 37
Please let me know if anybody has any ideas on how to do this as efficiently as possible, because this dictionary has probably over a thousand pairs. Thank you.
EDIT:
Using exec works well, but I oversimplified in the original post. I need the variable to be a dictionary so when I open multiple files I can append values.
Basic idea is to use 'exec' function like below.
nat = {
'abc': 1,
'a123': 2,
'a1b': 3,
'b31': 4
}
for k, v in nat.items():
exec("%s = %d" % (k, v))
print(k, v)
print(abc, a123, a1b, b31)
Note: It will only work if keys follows the variable name constraints
Avoid using eval(),Try setattr(I am not sure whether it is a better way.):
import sys
d = {"thisIsADummy": 37, 'a': [123,2]}
for k, v in d.items():
setattr(sys.modules[__name__], k, v)
a.append(1)
print(thisIsADummy, a)
Result:
37 [123, 2, 1]
Related
Given a dictionary { k1: v1, k2: v2 ... } I want to get { k1: f(v1), k2: f(v2) ... } provided I pass a function f.
Is there any such built in function? Or do I have to do
dict([(k, f(v)) for (k, v) in my_dictionary.iteritems()])
Ideally I would just write
my_dictionary.map_values(f)
or
my_dictionary.mutate_values_with(f)
That is, it doesn't matter to me if the original dictionary is mutated or a copy is created.
There is no such function; the easiest way to do this is to use a dict comprehension:
my_dictionary = {k: f(v) for k, v in my_dictionary.items()}
In python 2.7, use the .iteritems() method instead of .items() to save memory. The dict comprehension syntax wasn't introduced until python 2.7.
Note that there is no such method on lists either; you'd have to use a list comprehension or the map() function.
As such, you could use the map() function for processing your dict as well:
my_dictionary = dict(map(lambda kv: (kv[0], f(kv[1])), my_dictionary.iteritems()))
but that's not that readable, really.
These toolz are great for this kind of simple yet repetitive logic.
http://toolz.readthedocs.org/en/latest/api.html#toolz.dicttoolz.valmap
Gets you right where you want to be.
import toolz
def f(x):
return x+1
toolz.valmap(f, my_list)
Due to PEP-0469 which renamed iteritems() to items() and PEP-3113 which removed Tuple parameter unpacking, in Python 3.x you should write Martijn Pieters♦ answer like this:
my_dictionary = dict(map(lambda item: (item[0], f(item[1])), my_dictionary.items()))
You can do this in-place, rather than create a new dict, which may be preferable for large dictionaries (if you do not need a copy).
def mutate_dict(f,d):
for k, v in d.iteritems():
d[k] = f(v)
my_dictionary = {'a':1, 'b':2}
mutate_dict(lambda x: x+1, my_dictionary)
results in my_dictionary containing:
{'a': 2, 'b': 3}
While my original answer missed the point (by trying to solve this problem with the solution to Accessing key in factory of defaultdict), I have reworked it to propose an actual solution to the present question.
Here it is:
class walkableDict(dict):
def walk(self, callback):
try:
for key in self:
self[key] = callback(self[key])
except TypeError:
return False
return True
Usage:
>>> d = walkableDict({ k1: v1, k2: v2 ... })
>>> d.walk(f)
The idea is to subclass the original dict to give it the desired functionality: "mapping" a function over all the values.
The plus point is that this dictionary can be used to store the original data as if it was a dict, while transforming any data on request with a callback.
Of course, feel free to name the class and the function the way you want (the name chosen in this answer is inspired by PHP's array_walk() function).
Note: Neither the try-except block nor the return statements are mandatory for the functionality, they are there to further mimic the behavior of the PHP's array_walk.
To avoid doing indexing from inside lambda, like:
rval = dict(map(lambda kv : (kv[0], ' '.join(kv[1])), rval.iteritems()))
You can also do:
rval = dict(map(lambda(k,v) : (k, ' '.join(v)), rval.iteritems()))
Just came accross this use case. I implemented gens's answer, adding a recursive approach for handling values that are also dicts:
def mutate_dict_in_place(f, d):
for k, v in d.iteritems():
if isinstance(v, dict):
mutate_dict_in_place(f, v)
else:
d[k] = f(v)
# Exemple handy usage
def utf8_everywhere(d):
mutate_dict_in_place((
lambda value:
value.decode('utf-8')
if isinstance(value, bytes)
else value
),
d
)
my_dict = {'a': b'byte1', 'b': {'c': b'byte2', 'd': b'byte3'}}
utf8_everywhere(my_dict)
print(my_dict)
This can be useful when dealing with json or yaml files that encode strings as bytes in Python 2
My way to map over dictionary
def f(x): return x+2
bill = {"Alice": 20, "Bob": 10}
d = {map(lambda x: f(x),bill.values())}
print('d: ',dict(d))
Results
: d: {22: 12}
Map over iterable in values within dictionary
bills = {"Alice": [20, 15, 30], "Bob": [10, 35]}
d= {map(lambda v: sum(v),bills.values())}
g= dict(map(lambda v: (v[0],sum(v[1])),bills.items()))
# prints
print('d: ',dict(d))
print('g: ',g)
Results
d: {65: 45}
g: {'Alice': 65, 'Bob': 45}
so I have some problems with my dictionaries in python. For example I have dictionary like below:
d1 = {123456:xyz, 892019:kjl, 102930491:{[plm,kop]}
d2= {xyz:987, kjl: 0902, plm: 019240, kop:09829}
And I would like to have nested dictionary that looks something like that.
d={123456 :{xyz:987}, 892019:{kjl:0902}, 102930491:{plm:019240,kop:09829}}
is this possible? I was searching for nested dictionaries but nothing works for me.
You just need to loop through d1 and assign the correct values from d2.
Code:
d1 = {123456:'xyz', 892019:'kjl', 102930491:['plm','kop']}
d2 = {'xyz':987, 'kjl': 902, 'plm': 19240, 'kop':9829}
result = {}
for k, v in d1.items():
if isinstance(v, list):
result[k] = {k: d2.get(k) for k in v}
else:
result[k] = {v: d2.get(v)}
print(result)
Output:
{123456: {'xyz': 987}, 892019: {'kjl': 902}, 102930491: {'plm': 19240, 'kop': 9829}}
The above uses isintance() to check if the value is a list, so you can loop over it and assign the correct values from d2. It also uses dict.get() to ensure None is added if a KeyError was encountered when searching for a key in d2.
One-liner:
{k: {k: d2.get(k) for k in v} if isinstance(v, list) else {v: d2.get(v)} for k, v in d1.items()}
But this becomes messy and less maintainable.
First, you hate to put brackets around your keys and values.
d1 = {'123456':'xyz', '892019':'kjl', '102930491':'plm'}
d2= {'xyz':'987', 'kjl':'0902', 'plm':'019240', 'kop':'09829'}
Then I suggest you do a for loop
for key, value in d1.iter():
d1[key] = d2[value]
I have ignored your {[plm,kop]} thing. But it wont be difficult to implement it if you understand this first example.
Given a dictionary { k1: v1, k2: v2 ... } I want to get { k1: f(v1), k2: f(v2) ... } provided I pass a function f.
Is there any such built in function? Or do I have to do
dict([(k, f(v)) for (k, v) in my_dictionary.iteritems()])
Ideally I would just write
my_dictionary.map_values(f)
or
my_dictionary.mutate_values_with(f)
That is, it doesn't matter to me if the original dictionary is mutated or a copy is created.
There is no such function; the easiest way to do this is to use a dict comprehension:
my_dictionary = {k: f(v) for k, v in my_dictionary.items()}
In python 2.7, use the .iteritems() method instead of .items() to save memory. The dict comprehension syntax wasn't introduced until python 2.7.
Note that there is no such method on lists either; you'd have to use a list comprehension or the map() function.
As such, you could use the map() function for processing your dict as well:
my_dictionary = dict(map(lambda kv: (kv[0], f(kv[1])), my_dictionary.iteritems()))
but that's not that readable, really.
These toolz are great for this kind of simple yet repetitive logic.
http://toolz.readthedocs.org/en/latest/api.html#toolz.dicttoolz.valmap
Gets you right where you want to be.
import toolz
def f(x):
return x+1
toolz.valmap(f, my_list)
Due to PEP-0469 which renamed iteritems() to items() and PEP-3113 which removed Tuple parameter unpacking, in Python 3.x you should write Martijn Pieters♦ answer like this:
my_dictionary = dict(map(lambda item: (item[0], f(item[1])), my_dictionary.items()))
You can do this in-place, rather than create a new dict, which may be preferable for large dictionaries (if you do not need a copy).
def mutate_dict(f,d):
for k, v in d.iteritems():
d[k] = f(v)
my_dictionary = {'a':1, 'b':2}
mutate_dict(lambda x: x+1, my_dictionary)
results in my_dictionary containing:
{'a': 2, 'b': 3}
While my original answer missed the point (by trying to solve this problem with the solution to Accessing key in factory of defaultdict), I have reworked it to propose an actual solution to the present question.
Here it is:
class walkableDict(dict):
def walk(self, callback):
try:
for key in self:
self[key] = callback(self[key])
except TypeError:
return False
return True
Usage:
>>> d = walkableDict({ k1: v1, k2: v2 ... })
>>> d.walk(f)
The idea is to subclass the original dict to give it the desired functionality: "mapping" a function over all the values.
The plus point is that this dictionary can be used to store the original data as if it was a dict, while transforming any data on request with a callback.
Of course, feel free to name the class and the function the way you want (the name chosen in this answer is inspired by PHP's array_walk() function).
Note: Neither the try-except block nor the return statements are mandatory for the functionality, they are there to further mimic the behavior of the PHP's array_walk.
To avoid doing indexing from inside lambda, like:
rval = dict(map(lambda kv : (kv[0], ' '.join(kv[1])), rval.iteritems()))
You can also do:
rval = dict(map(lambda(k,v) : (k, ' '.join(v)), rval.iteritems()))
Just came accross this use case. I implemented gens's answer, adding a recursive approach for handling values that are also dicts:
def mutate_dict_in_place(f, d):
for k, v in d.iteritems():
if isinstance(v, dict):
mutate_dict_in_place(f, v)
else:
d[k] = f(v)
# Exemple handy usage
def utf8_everywhere(d):
mutate_dict_in_place((
lambda value:
value.decode('utf-8')
if isinstance(value, bytes)
else value
),
d
)
my_dict = {'a': b'byte1', 'b': {'c': b'byte2', 'd': b'byte3'}}
utf8_everywhere(my_dict)
print(my_dict)
This can be useful when dealing with json or yaml files that encode strings as bytes in Python 2
My way to map over dictionary
def f(x): return x+2
bill = {"Alice": 20, "Bob": 10}
d = {map(lambda x: f(x),bill.values())}
print('d: ',dict(d))
Results
: d: {22: 12}
Map over iterable in values within dictionary
bills = {"Alice": [20, 15, 30], "Bob": [10, 35]}
d= {map(lambda v: sum(v),bills.values())}
g= dict(map(lambda v: (v[0],sum(v[1])),bills.items()))
# prints
print('d: ',dict(d))
print('g: ',g)
Results
d: {65: 45}
g: {'Alice': 65, 'Bob': 45}
I am currently trying to make a function which reverses a dict's keys and values. I was looking online and came across this:
def reverse(d):
return dict([(v, k) for k, v in d.iteritems()])
My problem is that I'm not sure what this means. I understand the idea of a for loop on the single line but I'm not sure how the (v, k) for k, v leads to the keys and values being reversed. Could someone please offer me a hand. (I did search for this, both online and on Stack Overflow but couldn't find anything.)
for k, v in d.iteritems() is each key k and value v so reversing v and k with (v, k) makes the old value the key and the old key the new value
In [7]: d = {1:10,2:20}
In [8]: d.items()
Out[8]: dict_items([(1, 10), (2, 20)]) # tuples of key and value
In [1]: d = {1:10,2:20}
In [2]: for k,v in d.iteritems():
print k,v
...:
1 10 # 1 is the key 10 is the value
2 20
In [3]: new_d = {v:k for k,v in d.iteritems()} # swap key for value and value for key
In [4]: new_d
Out[4]: {10: 1, 20: 2}
Two problems you may encounter are duplicate values or values that are not hashable so they cannot be used as keys like lists, sets etc...
In [5]: d = {1:2,2:2}
In [6]: new_d = {v:k for k,v in d.iteritems()}
In [7]: new_d
Out[7]: {2: 2} # now only one key and value in the dict
In [8]: d = {1:2,2:[2]}
In [9]: new_d = {v:k for k,v in d.iteritems()}
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-9-46a3901ce850> in <module>()
----> 1 new_d = {v:k for k,v in d.iteritems()}
<ipython-input-9-46a3901ce850> in <dictcomp>((k, v))
----> 1 new_d = {v:k for k,v in d.iteritems()}
TypeError: unhashable type: 'list'
dict([(v, k) for k, v in d.iteritems()]) will have the same output as {v:k for k,v in d.iteritems()}, the main difference is the former is also compatible with python < 2.7.
If you were using python < 2.7 there is no need to use a list you can just use a generator expression:
dict((v, k) for k, v in d.iteritems())
the dict constructor can receive an iterable of key/value pairs to create a dictionary, so this code is saying "grab the key/value pairs from this dictionary d and create a new dictionary where the values of d are now the keys and the keys of d become the values"
That is why that the (v,k) are reversed, if you did NOT reverse them, like this
def reverse(d):
return dict([(k, v) for k, v in d.iteritems()])
you would get an identical dictionary back.
also note that in python 2.7 and later you can actually use the even more compact:
{v:k for k,v in d.items()}
Which reads more intuitively (at least to me) because it looks more like a list comprehension, only it creates a dict.
OK, so when you call iteritems() on a dict, it gives you a (key, value) tuple for each item in your dictionary:
for item in d.iteritems():
print(item)
Then you can assign each item in the tuple to a separate variable using Python's
tuple unpacking syntax:
a, b = (1, 2)
print(a) # 1
print(b) # 2
And if you pass a list of tuples to dict(), it treats them as a list
of (key, value) items:
eg_dict = dict([(a, 4), (b, 6)])
print(eg_dict)
Finally, the example you posted makes use of Python's list comprehension
syntax:
item_list = ['item' + str(n) for n in range(1, 6)]
print(item_list)
To understand the code snippet you've posted, you just need to be
familiar with these Python idioms. If you haven't seen any
of these techniques before then it's a fairly dense burst
of new information to get your head around.
This question already has answers here:
How to filter a dictionary according to an arbitrary condition function?
(7 answers)
Closed 7 years ago.
I have a dictionary of string keys and float values.
mydict = {}
mydict["joe"] = 20
mydict["bill"] = 20.232
mydict["tom"] = 0.0
I want to filter the dictionary to only include pairs that have a value greater than zero.
In C#, I would do something like this:
dict = dict.Where(r=>r.Value > 0);
What is the equivalent code in Python?
d = dict((k, v) for k, v in d.iteritems() if v > 0)
In Python 2.7 and up, there's nicer syntax for this:
d = {k: v for k, v in d.items() if v > 0}
Note that this is not strictly a filter because it does create a new dictionary.
Assuming your original dictionary is d1 you could use something like:
d2 = dict((k, v) for k, v in d1.items() if v > 0)
By the way, note that dict is already reserved in python.
The dict constructor can take a sequence of (key,value) pairs, and the iteritems method of a dict produces a sequence of (key,value) pairs. It's two great tastes that taste great together.
newDict = dict([item for item in oldDict.iteritems() if item[1] > 0])
foo = {}
foo["joe"] = 20
foo["bill"] = 20.232
foo["tom"] = 0.0
bar = dict((k,v) for k,v in foo.items() if v>0)
dict is a keyword in Python so I replaced it with foo.
first of all you should not use the keyword dict as a variable name as it pollutes the namespace, and prevents you from referencing the dict class in the current or embedded scope.
d = {}
d["joe"] = 20
d["bill"] = 20.232
d["tom"] = 0.0
# create an intermediate generator that is fed into dict constructor
# via a list comprehension
# this is more efficient that the pure "[...]" variant
d2 = dict(((k, v) for (k, v) in d.iteritems() if v > 0))
print d2
# {'bill': 20.232, 'joe': 20}
Alternatively, you could just create the generator and iterator over it directly. This more like a "filter", because the generator only references the values in the original dict instead of making a subset copy; and hence is more efficient than creating a new dictionary :
filtered = ((k, v) for (k, v) in d.iteritems() if v > 0)
print filtered
# <generator object <genexpr> at 0x034A18F0>
for k, v in filtered:
print k, v
# bill 20.232
# joe 20
try
y = filter(lambda x:dict[x] > 0.0,dict.keys())
the lambda is feed the keys from the dict, and compares the values in the dict for each key, against the criteria, returning back the acceptable keys.