Can I simplify this for loop with a one-line code? - python

my_dict = {'a':'1', 'b':2, 'c':3}
my_list = ['a','b','d']
for element in my_list:
if element not in my_dict:
my_dict[element] =1
Can this for loop be replaced by a one-line code in Python? I can't use dict or list comprehension to do it.

You can pass a dict into update():
my_dict = {'a':'1', 'b':2, 'c':3}
my_list = ['a','b','d']
my_dict.update({k:1 for k in my_list if k not in my_dict })
my_dict
# {'a': '1', 'b': 2, 'c': 3, 'd': 1}

you can do something like this:
for element in my_list:my_dict[element] = 1 if element not in my_dict else None;my_dict.pop(element) if my_dict[element] == None else ...

for k in my_list: my_dict[k] = 1 if k not in my_dict else my_dict[k]

The following code will work the same way.
dct = {'a':'1', 'b':2, 'c':3}
dct = {element: 1 if element not in dct else dct[element] for element in list(dct.keys()) + my_list }
print(dct);

You could use unpacking to produce a new merged dictionary:
my_dict = {**dict.fromkeys(my_list,1),**my_dict}
or an in-place update with the get function's default parameter set to 1:
my_dict.update((k,my_dict.get(k,1)) for k in my_list)

Related

Looping through all keys in a tuple of dictionaries

I have created the following dictionaries and a tuple:
dict1 = {'a':1,'b':2}
dict2 = {'c':3,'d':4}
dict3 = {'e':5,'f':6}
tuple_purse = dict1, dict2, dict3
I want to loop and print out all the keys in all the dictionaries in tuple_purse. I tried the following code:
for key in tuple_purse:
print(key)
for key,value in tuple_purse:
print(key)
And got the following output:
{'a': 1, 'b': 2}
{'c': 3, 'd': 4}
{'e': 5, 'f': 6}
a
c
e
Is there a way to loop through all the keys: a,b,c,d,e,f elegantly?
Thanks.
You can use chain from itertools.
Make an iterator that returns elements from the first iterable until it is exhausted, then proceeds to the next iterable, until all of the iterables are exhausted. Used for treating consecutive sequences as a single sequence
import itertools
dict1 = {'a':1,'b':2}
dict2 = {'c':3,'d':4}
dict3 = {'e':5,'f':6}
tuple_purse = dict1, dict2, dict3
for x in itertools.chain.from_iterable(tuple_purse):
print(x)
A simple quick double for perhaps? Do you need something more?
for ddict in tuple_purse:
for key in ddict:
print(key)
You can try this:
dict1 = {'a':1,'b':2}
dict2 = {'c':3,'d':4}
dict3 = {'e':5,'f':6}
tuple_dict = {**dict1, **dict2, **dict3}
for i in tuple_dict:
print(i, tuple_dict[i])
Note that for the solution above, the code will fail if there are multiple keys of the same name in two or more of the dicts.
Output:
a 1
b 2
c 3
d 4
e 5
f 6
Python2 solution
new_list = [dict1, dict2, dict3]
for d in new_list:
for k in d:
print k, d[k]
Output:
a 1
b 2
c 3
d 4
e 5
f 6

Differentiating two dictionaries key sets to generate result dictionary

I have,
dict1={a:1, b:2, c:3}
dict2={a:3, c:7}
I want to find out what keys I have in dict1 that I don't have in dict2. So I do
diff_as_set = set(dict1.keys()) - set (dict2.keys())
This gives me: b
However, I want a dictionary which contains all the key value mappings from dict1 for all keys that are not in dict 2 so I then do:
diff_as_dict = {k:v for k,v in dict1 if k in diff_as_set}
I get:
diff_as_dict = {k:v for k, v in dict1 if k in diff_as_set}
ValueError: too many values to unpack (expected 2)
Any ideas?
Looping over a dict only provides keys, you need to use:
diff_as_dict = {k:v for k, v in dict1.iteritems() if k in diff_as_set}
^^^^^^^^^^^
Or use .items() for Python 3.x
Instead of going through the entire dict to pick out the ones that match your set, just iterate the set.
diff_as_dict = {k:dict1[k] for k in diff_as_set}
Example:
>>> dict1={'a':1, 'b':2, 'c':3}
>>> dict2={'a':3, 'c':7}
>>> diff_as_set = set(dict1.keys()) - set (dict2.keys())
>>> diff_as_set
set(['b'])
>>> diff_as_dict = {k:dict1[k] for k in diff_as_set}
>>> diff_as_dict
{'b': 2}
You're missing the .iteritems() part:
dict1 = {'a':1, 'b':2, 'c':3}
dict2 = {'a':3, 'c':7}
newdict = {k : v for k,v in dict1.iteritems() if not(k in dict2)}
After this, newdict is equal to {'b': 2}. This does everything in one go.

Modify all values in a dictionary

Code goes below:
d = {'a':0, 'b':0, 'c':0, 'd':0} #at the beginning, all the values are 0.
s = 'cbad' #a string
indices = map(s.index, d.keys()) #get every key's index in s, i.e., a-2, b-1, c-0, d-3
#then set the values to keys' index
d = dict(zip(d.keys(), indices)) #this is how I do it, any better way?
print d #{'a':2, 'c':0, 'b':1, 'd':3}
Any other way to do that?
PS. the code above is just a simple one to demonstrate my question.
Something like this might make your code more readable:
dict([(x,y) for y,x in enumerate('cbad')])
But you should give more details what you really want to do. Your code will probably fail if the characters in s do not fit the keys of d. So d is just a container for the keys and the values are not important. Why not start with a list in that case?
use update() method of dict:
d.update((k,s.index(k)) for k in d.iterkeys())
What about
d = {'a':0, 'b':0, 'c':0, 'd':0}
s = 'cbad'
for k in d.iterkeys():
d[k] = s.index(k)
? It's no functional programming anymore but should be more performant and more pythonic, perhaps :-).
EDIT: A function variant using python dict-comprehensions (needs Python 2.7+ or 3+):
d.update({k : s.index(k) for k in d.iterkeys()})
or even
{k : s.index(k) for k in d.iterkeys()}
if a new dict is okay!
for k in d.iterkeys():
d[k] = s.index[k]
Or, if you don't already know the letters in the string:
d = {}
for i in range(len(s)):
d[s[i]]=i
another one liner:
dict([(k,s.index(k)) for (k,v) in d.items()])
You don't need to pass a list of tuples to dict. Instead, you can use a dictionary comprehension with enumerate:
s = 'cbad'
d = {v: k for k, v in enumerate(s)}
If you need to process the intermediary steps, including initial setting of values, you can use:
d = dict.fromkeys('abcd', 0)
s = 'cbad'
indices = {v: k for k, v in enumerate(s)}
d = {k: indices[k] for k in d} # dictionary comprehension
d = dict(zip(d, map(indices.get, d))) # dict + zip alternative
print(d)
# {'a': 2, 'b': 1, 'c': 0, 'd': 3}
You choose the right way but think that no need to create dict and then modify it if you have ability to do this in the same time:
keys = ['a','b','c','d']
strK = 'bcad'
res = dict(zip(keys, (strK.index(i) for i in keys)))
Dict comprehension for python 2.7 and above
{key : indice for key, indice in zip(d.keys(), map(s.index, d.keys()))}
>>> d = {'a':0, 'b':0, 'c':0, 'd':0}
>>> s = 'cbad'
>>> for x in d:
d[x]=s.find(x)
>>> d
{'a': 2, 'c': 0, 'b': 1, 'd': 3}

Dictionary keys match on list; get key/value pair

In python... I have a list of elements 'my_list', and a dictionary 'my_dict' where some keys match in 'my_list'.
I would like to search the dictionary and retrieve key/value pairs for the keys matching the 'my_list' elements.
I tried this...
if any(x in my_dict for x in my_list):
print set(my_list)&set(my_dict)
But it doesn't do the job.
(I renamed list to my_list and dict to my_dict to avoid the conflict with the type names.)
For better performance, you should iterate over the list and check for membership in the dictionary:
for k in my_list:
if k in my_dict:
print(k, my_dict[k])
If you want to create a new dictionary from these key-value pairs, use
new_dict = {k: my_dict[k] for k in my_list if k in my_dict}
Don't use dict and list as variable names. They shadow the built-in functions. Assuming list l and dictionary d:
kv = [(k, d[k]) for k in l if k in d]
new_dict = dict((k, v) for k, v in dict.iteritems() if k in list)
Turning list into a set set(list) may yield a noticeable speed increase
Try This:
mydict = {'one': 1, 'two': 2, 'three': 3}
mykeys = ['three', 'one','ten']
newList={k:mydict[k] for k in mykeys if k in mydict}
print newList
{'three': 3, 'one': 1}
What about print([kv for kv in dict.items() if kv[0] in list])
Here is a one line solution for that
{i:my_dict[i] for i in set(my_dict.keys()).intersection(set(my_list))}

How do I exchange keys with values in a dictionary? [duplicate]

This question already has answers here:
Reverse / invert a dictionary mapping
(32 answers)
Closed 10 months ago.
I receive a dictionary as input, and would like to to return a dictionary whose keys will be the input's values and whose value will be the corresponding input keys. Values are unique.
For example, say my input is:
a = dict()
a['one']=1
a['two']=2
I would like my output to be:
{1: 'one', 2: 'two'}
To clarify I would like my result to be the equivalent of the following:
res = dict()
res[1] = 'one'
res[2] = 'two'
Any neat Pythonic way to achieve this?
Python 2:
res = dict((v,k) for k,v in a.iteritems())
Python 3 (thanks to #erik):
res = dict((v,k) for k,v in a.items())
new_dict = dict(zip(my_dict.values(), my_dict.keys()))
From Python 2.7 on, including 3.0+, there's an arguably shorter, more readable version:
>>> my_dict = {'x':1, 'y':2, 'z':3}
>>> {v: k for k, v in my_dict.items()}
{1: 'x', 2: 'y', 3: 'z'}
You can make use of dict comprehensions:
Python 3
res = {v: k for k, v in a.items()}
Python 2
res = {v: k for k, v in a.iteritems()}
Edited: For Python 3, use a.items() instead of a.iteritems(). Discussions about the differences between them can be found in iteritems in Python on SO.
In [1]: my_dict = {'x':1, 'y':2, 'z':3}
Python 3
In [2]: dict((value, key) for key, value in my_dict.items())
Out[2]: {1: 'x', 2: 'y', 3: 'z'}
Python 2
In [2]: dict((value, key) for key, value in my_dict.iteritems())
Out[2]: {1: 'x', 2: 'y', 3: 'z'}
The current leading answer assumes values are unique which is not always the case. What if values are not unique? You will loose information!
For example:
d = {'a':3, 'b': 2, 'c': 2}
{v:k for k,v in d.iteritems()}
returns {2: 'b', 3: 'a'}.
The information about 'c' was completely ignored.
Ideally it should had be something like {2: ['b','c'], 3: ['a']}. This is what the bottom implementation does.
Python 2.x
def reverse_non_unique_mapping(d):
dinv = {}
for k, v in d.iteritems():
if v in dinv:
dinv[v].append(k)
else:
dinv[v] = [k]
return dinv
Python 3.x
def reverse_non_unique_mapping(d):
dinv = {}
for k, v in d.items():
if v in dinv:
dinv[v].append(k)
else:
dinv[v] = [k]
return dinv
You could try:
Python 3
d={'one':1,'two':2}
d2=dict((value,key) for key,value in d.items())
d2
{'two': 2, 'one': 1}
Python 2
d={'one':1,'two':2}
d2=dict((value,key) for key,value in d.iteritems())
d2
{'two': 2, 'one': 1}
Beware that you cannot 'reverse' a dictionary if
More than one key shares the same value. For example {'one':1,'two':1}. The new dictionary can only have one item with key 1.
One or more of the values is unhashable. For example {'one':[1]}. [1] is a valid value but not a valid key.
See this thread on the python mailing list for a discussion on the subject.
res = dict(zip(a.values(), a.keys()))
new_dict = dict( (my_dict[k], k) for k in my_dict)
or even better, but only works in Python 3:
new_dict = { my_dict[k]: k for k in my_dict}
Another way to expand on Ilya Prokin's response is to actually use the reversed function.
dict(map(reversed, my_dict.items()))
In essence, your dictionary is iterated through (using .items()) where each item is a key/value pair, and those items are swapped with the reversed function. When this is passed to the dict constructor, it turns them into value/key pairs which is what you want.
Suggestion for an improvement for Javier answer :
dict(zip(d.values(),d))
Instead of d.keys() you can write just d, because if you go through dictionary with an iterator, it will return the keys of the relevant dictionary.
Ex. for this behavior :
d = {'a':1,'b':2}
for k in d:
k
'a'
'b'
Can be done easily with dictionary comprehension:
{d[i]:i for i in d}
dict(map(lambda x: x[::-1], YourDict.items()))
.items() returns a list of tuples of (key, value). map() goes through elements of the list and applies lambda x:[::-1] to each its element (tuple) to reverse it, so each tuple becomes (value, key) in the new list spitted out of map. Finally, dict() makes a dict from the new list.
Hanan's answer is the correct one as it covers more general case (the other answers are kind of misleading for someone unaware of the duplicate situation). An improvement to Hanan's answer is using setdefault:
mydict = {1:a, 2:a, 3:b}
result = {}
for i in mydict:
result.setdefault(mydict[i],[]).append(i)
print(result)
>>> result = {a:[1,2], b:[3]}
Using loop:-
newdict = {} #Will contain reversed key:value pairs.
for key, value in zip(my_dict.keys(), my_dict.values()):
# Operations on key/value can also be performed.
newdict[value] = key
If you're using Python3, it's slightly different:
res = dict((v,k) for k,v in a.items())
Adding an in-place solution:
>>> d = {1: 'one', 2: 'two', 3: 'three', 4: 'four'}
>>> for k in list(d.keys()):
... d[d.pop(k)] = k
...
>>> d
{'two': 2, 'one': 1, 'four': 4, 'three': 3}
In Python3, it is critical that you use list(d.keys()) because dict.keys returns a view of the keys. If you are using Python2, d.keys() is enough.
I find this version the most comprehensive one:
a = {1: 'one', 2: 'two'}
swapped_a = {value : key for key, value in a.items()}
print(swapped_a)
output :
{'one': 1, 'two': 2}
An alternative that is not quite as readable (in my opinion) as some of the other answers:
new_dict = dict(zip(*list(zip(*old_dict.items()))[::-1]))
where list(zip(*old_dict.items()))[::-1] gives a list of 2 tuples, old_dict's values and keys, respectively.

Categories