find key value based on value field python dictionary - python

I have a dictionary where the values are lists. I would like to look for a specific value in the lists (value field of dictionary) and return the key value:
dict={'a':['ab','cd','ef'], 'b':['gh', 'ij'], 'c':['kl', 'mn']}
So for 'ef' I would get 'a', for 'mn' I would get 'c'...
I have tryied
value_key=[a for a,b in dict if value in b]
Any ideas?

Assuming you want to do indexing this way more than once, you should build the reverse mapping, from values (sub-values really) to keys:
{ vsub:k for k, v in d.iteritems() for vsub in v }
This takes your original dict (called d here because dict is a builtin name in Python), and "inverts" it, with the tweak of mapping each sub-value (the elements within the lists).
Once you have this new dict, you can simply index into it by keys like 'ab' to get 'a':
{'ab': 'a', 'ef': 'a', 'mn': 'c', 'kl': 'c', 'ij': 'b', 'cd': 'a', 'gh': 'b'}

Iterate through the dictionary with for key in dict_object, and then use in operator to check if the value being searched is in the dictionary's value corresponding to the key. If it exists, then retain the key for the output.
my_dict,val={"a": ["ab", "cd", "ef"], "b": ["gh", "ij"], "c": ["kl", "mn"]}, "ef"
print [key for key in my_dict if val in my_dict[key]]
# ['a']
The advantage of this method is, it will work irrespective of the current popular Python versions, as we don't have to worry about items and iteritems methods.

Related

How to extract common elements of values (which are lists) of dictionary and map them back to their keys as their new values? [duplicate]

This question already has answers here:
Inverting a dictionary with list values
(6 answers)
Closed 9 months ago.
I have a dictionary:
dict = {'A':[1,2,5],'B':[3,6,13],'C':[2,3,6],'D':[4,6,8]}
I want to extract all the common elements into a new dictionary as keys with their corresponding values as the keys in dict which they are extracted from.
What I want is:
newdict = {1:['A'],2:['A','C'],3:['B','C'],4:['D'],5:['A'],6:['B','C','D'],8:['D'],13:['B']} .
I have tried to compare values of each element by copying the dictionary dict and comparing each of the elements (dict1 is copy of dict):
for i, j in zip(range(len(dict)), range(len(dict1))):
for m, n in zip(range(len(dict[i])), range(len(dict1[j]))):
if dict[i][m] == dict1[j][n]:
print(dict[i][m])
for i in range(len(dict)):
for k in range(len(dict[i])):
#print(dict[i][k])
for j in range(dict[i+1][k], len(g)):
#print(j)
if dict[i][k] == dict[i+1][j]:
print(dict[i][k])
However, I ended up with index out of range error or unable to get the proper keys even before being able to extract the common repeating values. Does anybody know how to do this?
Simple solution using defaultdict (to reduce bloat code)
from collections import defaultdict
d2 = defaultdict(list)
for k,v in d.items():
for number in v:
d2[number].append(k)
>>> print(d2)
defaultdict(list,
{1: ['A'],
2: ['A', 'C'],
3: ['B', 'C'],
4: ['D'],
5: ['A'],
6: ['B', 'C', 'D'],
8: ['D'],
13: ['B']})
You can also use a normal dictionary, there's just some more checks to add:
d2 = {}
for k,v in d.items():
for number in v:
if number in d2:
d2[number].append(k)
else:
d2[number] = [k]
Finally, avoid naming your dictionary dict, since it overwrites the built-in dict name.

Python3: Sort a 3-levels nested dictionary by value

I've been trying to sort a dictionary of dictionaries of dictionaries (3-levels) but had no luck. I need to sort it by the "common_RMSD" field value. This is an input example (sorry I don't know how to format properly the dictionary here...)
my_dict = {'E': {
'E': {
'common_sup': <Bio.PDB.Superimposer.Superimposer object at 0x08451030>,
'common_sample_chain_ID': 'E',
'common_ref_chain_ID': 'E',
'common_RMSD': 2.013799285922141e-14},
'F': {
'common_sup': <Bio.PDB.Superimposer.Superimposer object at 0x08786FB0>,
'common_sample_chain_ID': 'F',
'common_ref_chain_ID': 'E',
'common_RMSD': 0.1207801497077146}},
'F': {
'E': {
'common_sup': <Bio.PDB.Superimposer.Superimposer object at 0x08AB6410>,
'common_sample_chain_ID': 'E',
'common_ref_chain_ID': 'F',
'common_RMSD': 0.12078014970771417},
'F': {
'common_sup': <Bio.PDB.Superimposer.Superimposer object at 0x08AB63F0>,
'common_sample_chain_ID': 'F',
'common_ref_chain_ID': 'F',
'common_RMSD': 7.559143985024071e-15}
} }
I have read in previous posts the use of lamdda and items() functions. With items() I can get through the first value of the first key-value level (which is the second dictionary), but I don't know how to go further inside the dictionary.
sorted(dict.items(), key = lambda x: x[1]... )
Is there a possibility to reorder the whole dictionary, sorting the nested dictionaries by the 'common_RMSD' value? So that when I loop through them, the first dictionary has the lowest 'common_RMSD' value? If not, then output a tuple with ('common_sup','common_sample_chain_ID','common_ref_chain_ID','common_RMSD'), again ordered by 'common_RMSD'

Merge dictionaries with old keys when old value and new key is same

I want to merge two dictionaries like this:
old={'a':'1a','b':'1b','c':'1c'}
new={'1a':'c','1b':'d','1c':'e'}
I want output like this:
new_dict={'a':'c','b':'d','c':'e'}
Note: The length of both dictionaries is different.
How to do it in python?
With a dict-comprehension:
old = {'a': '1a','b': '1b','c': '1c'}
new = {'1a': 'c','1b': 'd','1c': 'e'}
res = {k: new[v] for k, v in old.items()} # if all values in `old` exist in `new` as keys.
res = {k: new.get(v, None) for k, v in old.items()} # if you cannot guarantee the above.
print(res) # {'b': 'd', 'a': 'c', 'c': 'e'}
*Note that the None parameter of the .get() method is the default one and as such, it can be omitted. I will leave it there though to remind you that you can specify anything you want depending on the specifics of your problem (e.g., '' (blank string) might be better in your case)
You can get the new dictionary using a dictionary comprehension where you get the values from the new dictionary based on the keys in the old dictionary. Be sure to use get which returns None by default if a value from the old dictionary is not present as a key in the new dictionary.
old = {'a': '1a', 'b': '1b' ,'c': '1c'}
new = {'1a': 'c', '1b': 'd', '1c': 'e'}
new_dict = {k: new.get(old[k]) for k in old}
>>> new_dict
{'a': 'c', 'b': 'd', 'c': 'e'}
You could use a dictionary comprehension that interprets the value of the first dictionary as the key of the second dictionary:
>>> {item: new[value] for item, value in old.items() if value in new}
{'a': 'c', 'b': 'd', 'c': 'e'}
In case you can garantuee that all values of old are in new you could omit the if value in new part.

is it possible to reverse a dictionary in python using dictionary comprehension

I want to reverse dictionary key, value pairs using a dictionary comprehension, but if the new dictionary has more than one value for a key then it is getting replaced with the last value.
Is it possible to append to the values in the new dictionary if a key is repeated, using a comprehension?
Input:
test_di = {'a':'1', 'b':'2', 'c':'3', 'd':'2'}
Code:
{v:k for k,v in test_di.items()}
Output of this code:
{'1': 'a', '3': 'c', '2': 'd'}
Desired output:
{'1': ['a'], '3': ['c'], '2': ['b','d']}
It's not possible to do it in a reasonable way (i.e. O(N) time) with a dictionary comprehension. The comprehension simply can't handle duplicated values.
However, it's quite easy with a regular loop:
d = {}
for key, value in old_d.items():
d.setdefault(value, []).append(key)
A defaultdict would be the most efficient approach:
from collections import defaultdict
test_di = {'a':'1', 'b':'2', 'c':'3', 'd':'2'}
d = defaultdict(list)
for v,k in test_di.items():
d[k].append(v)
print(d)
Your question is confusing, but it sounds like you want to store multiple values at a single key in a dictionary.
This is not possible, you may want to look at storing a dictionary of lists.
You can use an OrderedDict and reverse the keys. A normal dict does not keep track of the order of the keys.
from collections import OrderedDict
dict1 = OrderedDict([('Name', 'Jon'), ('Race', 'Latino'), ('Job', 'Nurse')])
reversed_dict1 = OrderedDict([(key, dict1.get(key)) for key in reversed(dict1)])
Yes, it is possible (but it’s not the most efficient solution):
d = {'a':'1', 'b':'2', 'c':'3', 'd':'2'}
{v1: [k1 for k1, v2 in d.items() if v1 == v2] for v1 in d.values()}
# {'1': ['a'], '2': ['b', 'd'], '3': ['c']}

Python:How to determine whether the dictionary contains multiple keys?

d={'a':1, 'b':2, ...}
if 'a' in d and 'b' in d and ...:
pass
is there a simple way to determine multiple keys at once?
something like:
if ['a', 'b'] in d:
You can do
if all(key in d for key in ['a', 'b', 'c', ...]):
This may be longer than writing them out separately if you're only testing a couple, but as the list of keys to be tested grows longer, this way will be quicker, since you only have to add the key to the list and not write an additional in d and.
d={'a':1, 'b':2, ...}
required_keys = set(('a', 'b', ...))
missing_keys = required_keys.difference(d.keys())
if missing_keys
print "You are missing some keys: ", missing_keys
else:
print "You have all of the required keys"
len(d.keys()) will let you know how many keys are in your dictionary

Categories