Call function for everly key,value in dictionary - python

Let's say we have a dict and specified function which takes two parameters as input
foo = {'key1':'value1', 'key2':'value2'}
def bar(key, value):
print key, value
Is is possible to call this function for every key value pair in one liner?
I know that I can do it in list/dict comprehension but I think this solution is not pythonic cause I dont return anyting in bar function. Is there any recommended and pythonic way to do that?

Use a for-loop over the .items method of the dictionary:
for item in foo.items():
bar(*item)
The * syntax unpacks the tuples (e.g. ('key1', 'value1')) into the arguments to a function. Note that you could do the unpacking in the for-loop too:
for k, v in foo.items():
bar(k, v)
Both of which give:
key2 value2
key1 value1
You may notice that they are in a different order to the order you defined them in. This is just an implicit feature of dictionaries - they have no (reliable) order. The reason I say "reliable" is because it is deterministic (based on each object's hash, but it is unwise to rely on this.

yes, you can with a tiny modification to your function
foo = {'key1':'value1', 'key2':'value2'}
def bar(pair):
key, value = pair
print key, value
With this function at hand, you can use map.
map(bar, foo.items())
that produces:
key2 value2
key1 value1

Quoting PEP-20
Simple is better than complex.
Read the Zen of Python
Keeping things simple, you could do something like -
def bar(key, value):
print key, value
for k, v in foo.items():
bar(k, v)

foo = {'key1':'value1', 'key2':'value2'}
def bar(key, value):
print key, value
[bar(key, value) for key,value in foo.items()]

Related

How to print all of the key/value pairs in a dictionary

Given a dictionary myDictionary, write a function that prints all of the key/value pairs of the dictionary, one per line, in the following format:
key: value
key: value
key: value
Use the following function header:
def printKeyValuePairs(myDictionary):
For example, if
myDictionary = {'The Beatles':10, 'Bob Dylan':10, 'Radiohead':5}
your function would print
The Beatles: 10
Bob Dylan: 10
Radiohead: 5
for key in myDictionary:
print("{}: {}".format(key, myDictionary[key]))
I read on SO somewhere there is a good reason not to either access dictionary values using myDictionary[key] over the following, or visa-versa, but I can't recall where (or if I'm remembering correctly).
for key, value in myDictionary.items():
print(f"{key}: {value}")
There are essentially two (modern) ways to do string formatting in Python, both covered in great detail [here][1]:
"var1: {}, var2: {}".format("VAR1", "VAR2")
f"var1: {"VAR1"}, var2: {"VAR2"}"
Both yield var1: var1, var2:VAR2, but the latter is only supported in Python 3.6+.
here is a simple function that prints all the key value pairs in a dictionary:
def printKeyValuePairs(myDictionary):
"""prints each key, value pair in a line"""
for key, val in myDictionary.items():
print("{}: {}".format(key, val))
if the a dictionary has the following key, value pairs:
my_dict = {'The Beatles':10, 'Bob Dylan':10, 'Radiohead':5}
if we call the function defined above, we get the following output:
printKeyValuePairs(my_dict)
The Beatles: 10
Bob Dylan: 10
Radiohead: 5

Merging values from 2 dictionaries (Python)

(I'm new to Python!)
Trying to figure out this homework question:
The function will takes a​s input​ two dictionaries, each mapping strings to integers. The function will r​eturn​ a dictionary that maps strings from the two input dictionaries to the sum of the integers in the two input dictionaries.
my idea was this:
def ​add(​dicA,dicB):
dicA = {}
dicB = {}
newdictionary = dicA.update(dicB)
however, that brings back None.
In the professor's example:
print(add({'alice':10, 'Bob':3, 'Carlie':1}, {'alice':5, 'Bob':100, 'Carlie':1}))
the output is:
{'alice':15, 'Bob':103, 'Carlie':2}
My issue really is that I don't understand how to add up the values from each dictionaries. I know that the '+' is not supported with dictionaries. I'm not looking for anyone to do my homework for me, but any suggestions would be very much appreciated!
From the documentation:
update([other])
Update the dictionary with the key/value pairs from other, overwriting existing keys. Return None.
You don't want to replace key/value pairs, you want to add the values for similar keys. Go through each dictionary and add each value to the relevant key:
def ​add(​dicA,dicB):
result = {}
for d in dicA, dicB:
for key in d:
result[key] = result.get(key, 0) + d[key]
return result
result.get(key, 0) will retrieve the value of an existing key or produce 0 if key is not yet present.
First of all, a.update(b) updates a in place, and returns None.
Secondly, a.update(b) wouldn't help you to sum the keys; it would just produce a dictionary with the resulting dictionary having all the key, value pairs from b:
>>> a = {'alice':10, 'Bob':3, 'Carlie':1}
>>> b = {'alice':5, 'Bob':100, 'Carlie':1}
>>> a.update(b)
>>> a
{'alice': 5, 'Carlie': 1, 'Bob': 100}
It'd be easiest to use collections.Counter to achieve the desired result. As a plus, it does support addition with +:
from collections import Counter
def add(dicA, dicB):
return dict(Counter(dicA) + Counter(dicB))
This produces the intended result:
>>> print(add({'alice':10, 'Bob':3, 'Carlie':1}, {'alice':5, 'Bob':100, 'Carlie':1}))
{'alice': 15, 'Carlie': 2, 'Bob': 103}
The following is not meant to be the most elegant solution, but to get a feeling on how to deal with dicts.
dictA = {'Alice':10, 'Bob':3, 'Carlie':1}
dictB = {'Alice':5, 'Bob':100, 'Carlie':1}
# how to iterate through a dictionary
for k,v in dictA.iteritems():
print k,v
# make a new dict to keep tally
newdict={}
for d in [dictA,dictB]: # go through a list that has your dictionaries
print d
for k,v in d.iteritems(): # go through each dictionary item
if not k in newdict.keys():
newdict[k]=v
else:
newdict[k]+=v
print newdict
Output:
Bob 3
Alice 10
Carlie 1
{'Bob': 3, 'Alice': 10, 'Carlie': 1}
{'Bob': 100, 'Alice': 5, 'Carlie': 1}
{'Bob': 103, 'Alice': 15, 'Carlie': 2}
def ​add(​dicA,dicB):
You define a function that takes two arguments, dicA and dicB.
dicA = {}
dicB = {}
Then you assign an empty dictionary to both those variables, overwriting the dictionaries you passed to the function.
newdictionary = dicA.update(dicB)
Then you update dicA with the values from dicB, and assign the result to newdictionary. dict.update always returns None though.
And finally, you don’t return anything from the function, so it does not give you any results.
In order to combine those dictionaries, you actually need to use the values that were passed to it. Since dict.update mutates the dictionary it is called on, this would change one of those passed dictionaries, which we generally do not want to do. So instead, we use an empty dictionary, and then copy the values from both dictionaries into it:
def add (dicA, dicB):
newDictionary = {}
newDictionary.update(dicA)
newDictionary.update(dicB)
return newDictionary
If you want the values to sum up automatically, then use a Counter instead of a normal dictionary:
from collections import Counter
def add (dicA, dicB):
newDictionary = Counter()
newDictionary.update(dicA)
newDictionary.update(dicB)
return newDictionary
I suspect your professor wants to achieve this using more simple methods. But you can achieve this very easily using collections.Counter.
from collections import Counter
def add(a, b):
return dict(Counter(a) + Counter(b))
Your professor probably wants something like this:
def add(a, b):
new_dict = copy of a
for each key/value pair in b
if key in new_dict
add value to value already present in new_dict
else
insert key/value pair into new_dict
return new_dict
You can try this:
def add(dict1, dict2):
return dict([(key,dict1[key]+dict2[key]) for key in dict1.keys()])
I personally like using a dictionary's get method for this kind of merge:
def add(a, b):
result = {}
for dictionary in (a, b):
for key, value in dictionary.items():
result[key] = result.get(key, 0) + value
return result

Dictionary Iterating -- for dict vs for dict.items()

When we iterate over the dictionary below, each iteration returns(correctly) a key,value pair
for key, value in dict.items():
print "%s key has the value %s" % (key, value)
'some key' key has the value 'some value' (repeated however many times there are a k,v pair)
The above makes sense to me, however if we do this:
for key in dict.items():
print "%s key has the value %s" % (key, value)
("some key", "some value") has the value "some value" (the left tuple will iterate through each key value pair and the right value will just stay at the first value in the dict and repeat)
We end up getting each k,v pair returned in the first %s (key) and the 2nd %s (value) does not iterate, it just returns the first value in the dict for each iteration of the for loop.
I understand that if you iterate with only for key in dict then you are iterating over the keys only. Here since we are iterating a set of tuples (by using dict.items()) with only the key in the for loop, the loop should run for the same number of times as the first example, since there are as many keys as key,value pairs.
What I'm having trouble grasping is why python gives you the entire tuple in the second example for key.
Thanks for the help all -- I'd like to add one more question to the mix.
for a,a in dict.items():
print a
Why does the above print the value, and if i print a,a - obviously both values are printed twice. If I had typed for a,b I would be iterating (key,value) pairs so I would logically think I am now iterating over (key,key) pairs and would therefore print key rather than value. Sorry for the basic questions just playing around in interpreter and trying to figure stuff out.
The first example is utilizing something known as "tuple unpacking" to break what is REALLY the same tuple as in your separate example down into two different variables.
In other words this:
for key, value in dict.items():
Is just this:
for keyvalue in dict.items():
key, value = keyvalue[0], keyvalue[1]
Remember that a for loop always iterates over the individual elements of the iterator you give it. dict.items() returns a list-like object of tuples, so every run through the for loop is a new tuple, automatically unpacked into key, value if you define it as such in the for loop.
It may help to think of it this way:
d = {'a':1, 'b':2, 'c':3}
list(d) # ['a', 'b', 'c'] the keys
list(d.keys()) # ['a', 'b', 'c'] the keys
list(d.values()) # [1, 2, 3] the values
list(d.items()) # [('a',1), ('b',2), ('c',3)] a tuple of (key, value)
N.B. that the only reason your code
for key in dict.items():
print "%s key has value: %s" % (key, value)
Does not throw a NameError is because value is already defined from elsewhere in your code. Since you do not define value anywhere in that for loop, it would otherwise throw an exception.
In the second example you gave you are not assigning "value" to anything:
Notice the small edit here:
for key in dict: ##Removed call to items() because we just want the key,
##Not the key, value pair
value = dict[key] # Added this line
print "%s key has the value %s (key, value)
Note:
In the second example, you could now call dict.keys() or just dict (referencing a dictionary in a for loop will return it's keys). Calling dict.items() will confusingly assign
key=(, )
which is probably not what you want.

Finding key from value in Python dictionary:

Fairly new to Python, still struggling with so much information.
All the documentation I've seen about dictionaries explain various ways of getting a value via a key - but I'm looking for a pythonic way to do the opposite - get a key via a value.
I know I can loop through the keys and inspect their values until I find the value I'm looking for and then grab the key, but I'm looking for a direct route.
There is no direct route. It's pretty easy with list comprehensions, though;
[k for k, v in d.iteritems() if v == desired_value]
If you need to do this occasionally and don't think it's worth while indexing it the other way as well, you could do something like:
class bidict(dict):
def key_with_value(self, value, default=None):
for k, v in self.iteritems():
if v == value:
return v
return default
def keys_with_value(self, value, default=None):
return [v for k, v in self.iteritems() if v == value]
Then d.key_with_value would behave rather like d.get, except the other way round.
You could also make a class which indexed it both ways automatically. Key and value would both need to be hashable, then. Here are three ways it could be implemented:
In two separate dicts, with the exposing some dict-like methods; you could perhaps do foo.by_key[key] or foo.by_value[value]. (No code given as it's more complicated and I'm lazy and I think this is suboptimal anyway.)
In a different structure, so that you could do d[key] and d.inverse[value]:
class bidict(dict):
def __init__(self, *args, **kwargs):
self.inverse = {}
super(bidict, self).__init__(key, value)
def __setitem__(self, key, value):
super(bidict, self).__setitem__(key, value)
self.inverse[value] = key
def __delitem__(self, key):
del self.inverse[self[key]]
super(bidict, self).__delitem__(key)
In the same structure, so that you could do d[key] and d[value]:
class bidict(dict):
def __setitem__(self, key, value):
super(bidict, self).__setitem__(key, value)
super(bidict, self).__setitem__(value, key)
def __delitem__(self, key):
super(bidict, self).__delitem__(self[key])
super(bidict, self).__delitem__(key)
(Notably absent from these implementations of a bidict is the update method which will be slightly more complex (but help(dict.update) will indicate what you'd need to cover). Without update, bidict({1:2}) wouldn't do what it was intended to, nor would d.update({1:2}).)
Also consider whether some other data structure would be more appropriate.
Since your dictionary can contain duplicate values (i.e. {'a': 'A', 'b': 'A'}), the only way to find a key from value is to iterate over the dictionary as you describe.
Or... build the opposite dictionary. you have to recreate it after each modification of the original dictionary.
Or... write a class that maintains both-ways dictionary. You will have to manage situations where duplicate value appears.
the first solution with the list comprehension is good.
but a small fix for python 3.x, instead of .iteritems() it should be just .items():
[k for k, v in d.items() if v == desired_value]
Building a opposite dictionary is not at all good manner as one or more key have same value but if you invert it you need to insert key:[value1,... ] structure which will lead you to another problem.

How does the performance of dictionary key lookups compare in Python?

How does:
dict = {}
if key not in dict:
dict[key] = foo
Compare to:
try:
dict[key]
except KeyError:
dict[key] = foo
ie, is the look up of a key in anyway faster than the linear search through dict.keys(), that I assume the first form will do?
Just to clarify one point: if key not in d doesn't do a linear search through d's keys. It uses the dict's hash table to quickly find the key.
You're looking for the setdefault method:
>>> r = {}
>>> r.setdefault('a', 'b')
'b'
>>> r
{'a': 'b'}
>>> r.setdefault('a', 'e')
'b'
>>> r
{'a': 'b'}
The answer depends on how often the key is already in the dict (BTW, has anyone mentioned to you how bad an idea it is to hide a builtin such as dict behind a variable?)
if key not in dct:
dct[key] = foo
If the key is in the dictionary this does one dictionary lookup. If the key is in the dictionary it looks up the dictionary twice.
try:
dct[key]
except KeyError:
dct[key] = foo
This may be slightly faster for the case where the key is in the dictionary, but throwing an exception has quite a big overhead, so it is almost always not the best option.
dct.setdefault(key, foo)
This one is slightly tricky: it always involves two dictionary lookups: the first one is to find the setdefault method in the dict class, the second is to look for key in the dct object. Also if foo is an expression it will be evaluated every time whereas the earlier options only evaluate it when they have to.
Also look at collections.defaultdict. That is the most appropriate solution for a large class of situations like this.
Try: my_dict.setdefault(key, default). It's slightly slower than the other options, though.
If key is in the dictionary, return its value. If not, insert key with a value of default and return default. default defaults to None.
#!/usr/bin/env python
example_dict = dict(zip(range(10), range(10)))
def kn(key, d):
if key not in d:
d[key] = 'foo'
def te(key, d):
try:
d[key]
except KeyError:
d[key] = 'foo'
def sd(key, d):
d.setdefault(key, 'foo')
if __name__ == '__main__':
from timeit import Timer
t = Timer("kn(2, example_dict)", "from __main__ import kn, example_dict")
print t.timeit()
t = Timer("te(2, example_dict)", "from __main__ import te, example_dict")
print t.timeit()
t = Timer("sd(2, example_dict)", "from __main__ import sd, example_dict")
print t.timeit()
# kn: 0.249855041504
# te: 0.244259119034
# sd: 0.375113964081
my_dict.get(key, foo) returns foo if key isn't in my_dict. The default value is None, so my_dict.get(key) will return None if key isn't in my_dict. The first of your options is better if you want to just add key to your dictionary. Don't worry about speed here. If you find that populating your dictionary is a hot spot in your program, then think about it. But it isn't. So don't.

Categories

Resources