I still have a solution but wonder if there is a more pythonic version with in-built Python tools.
The goal would be to avoid the for loop.
Does Python offer a technique (package) to solve this?
I have 2 lists of the same length, one representing keys (with possible duplicates) and the other the values.
keys = list('ABAA')
vals = [1, 2, 1, 3]
The expected result:
{
'A': [1, 1, 3],
'B': [2]
}
My working solution (with Python 3.9):
result = {}
for k, v in zip(keys, vals):
# create new entry with empty list
if k not in result:
result[k] = []
# store the value
result[k].append(v)
print(result)
Very similar to your solution (which is great btw), but you could zip the lists and use dict.setdefault:
out = {}
for k,v in zip(keys,vals):
out.setdefault(k, []).append(v)
Output:
{'A': [1, 1, 3], 'B': [2]}
Can use this:
keys = list('ABAA')
vals = [1, 2, 1, 3]
d = {}
for key in set(keys):
d[key] = [vals[i] for i in range(len(keys)) if keys[i] == key]
convert a list of map to a single map?
label_name_mapping = [{'a':1},{'b':2},{'c':3}]
label_name_mapping = {k: v for k, v in (x.items() for x in label_name_mapping)}
I want to get a single map:
label_name_mapping = {'a':1, 'b':2, 'c':3}
You don't iterate enough.
Both fors are on the same level of items in your main list. You have to nest the loops:
{k:v for x in label_name_mapping for k, v in x.items()}
Good point on iteration mentioned above. You can also try the built in update method for maps:
master_map = {}
for map in label_name_mapping:
master_map.update(map)
{'a': 1, 'c': 3, 'b': 2}
Do dictionaries allow for filtering based on key length? Altering dictionaries conditionally based on value seems straightforward, but what about doing the same with keys? i.e. what would it take to delete all dictionary keys that are not explicitly 4 characters long?
You could use a dictionary comprehension:
d = {'fooo': 1, 'bar': 2, 'foo': 3}
result = {k: v for k, v in d.items() if len(k) == 4}
print(result)
Output
{'fooo': 1}
As krflol mentioned, if you don't want to build a whole new dictionary but
rather just modify your old dictionary, a straightforward for loop will do:
my_dict = {"a": 1, "abcd": 4, "": 9, "xyzt": 16}
for k in list(my_dict):
if len(k) != 4:
del my_dict[k]
print(my_dict)
Another way could be using filter, like so :
my_dict = dict(filter(lambda k: len(k) != 4, my_dict.items()))
This can be accomplished as seen in the following:
new_dict = {k: v for k, v in old_dict.items() if len(k) == 4}
I was looking for a method to sort a dictionary in Python with its values, after a few attempts, is what it comes:
a = {<populated dict...>}
a = {v: k for k, v in a.items()}
a = {v: k for k, v in sorted(a.items())}
This code seems to work, but I think it's poor for performance, is there a better way?
You do not need to do the double key/value swap, you can do this:
a = {k: v for k, v in sorted(a.items(), key=lambda x: x[1])}
(sorted DOCS)
Test Code:
data = dict(a=1, b=3, c=2)
print(data)
data_sorted = {k: v for k, v in sorted(data.items(), key=lambda x: x[1])}
print(data_sorted)
Results:
From CPython 3.6:
{'a': 1, 'b': 3, 'c': 2}
{'a': 1, 'c': 2, 'b': 3}
By default, the dictionary is sorted based on keys, but the sorted function takes a function as a parameter using which you can alter the behaviour for
program.
d={'a':6,'b':4,'k':3}
print(sorted(d))
sorted_by_values= sorted(d,key=lambda x:d[x])
print(sorted_by_values)
The following code works for me. Not sure how efficient is this.
sorted_list_by_value=sorted(data_dict, key=data_dict.__getitem__)
from collections import OrderedDict
otherwise create a list of keys in the order you want.
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.