Processing dictionary of dictionaries - python

I have a dictionary - where the values are dictionaries themselves.
How do I extract the unique set of the values from the child dictionaries in the most efficient way?
{ 'A':{'A1':'A1V','B2':'A2V'..},
'B':{'B1':'B1V','B2':'B2V'...},
...}
Expected output:
['A1V','A2V','B1V','B2V'...]

In a single line:
>>> [val for dct in x.values() for val in dct.values()]
['A1V', 'A2V', 'B2V', 'B1V']
Assuming you named your dict of dict x.
You mentioned unique, in that case replace the list-comprehension by a set-comprehension:
>>> {val for dct in x.values() for val in dct.values()} # curly braces!
{'A1V', 'A2V', 'B1V', 'B2V'}

uniques = set()
for ukey, uvalue in outerdic.items():
for lkey, lvalue in uvalue.items():
uniques.add(lvalue)
print uniques
Using a set should work. New to stackoverflow, trying to figure out how syntax highlighting works.
This assumes that the dictionary is called outerdic.

dictionary = { 'A':{'A1':'A1V','B2':'A2V'},'B':{'B1':'B1V','B2':'B2V'}}
for key in dictionary.keys() :
dict1 = dictionary[key]
for key1 in dict1.keys():
print(dict1[key1])
Tried to keep it as simple as possible.

Related

Comparing the strings in key and value of the same dictionary

I am looking to solve a problem to compare the string of the key and value of the same dictionary.
To return a dictionary of all key and values where the value contains the key name as a substring.
a = {"ant":"antler", "bi":"bicycle", "cat":"animal"}
the code needs to return the result:
b = {"ant":"antler", "bi":"bi cycle"}
You can iterate through the dictionary and unpack the key and the value at the same time this way:
b = {}
for key, value in a.items():
if value in key:
b[value] = key
This will generate your wanted solution. It does that by unpacking both the key and the value and checking if they match afterward.
You can also shorten that code by using a dictionary comprehension:
b = {key:value for key, value in a.items() if key in value}
This short line does the exact same thing as the code before. It even uses the same functionalities with only one addition - a dictionary comprehension. That allows you to put all that code in one simple line and declare the dictionary on the go.
answer = {k:v for k,v in a.items() if k in v}
Notes:
to iterate over key: value pair we use dict.items();
to check if a string is inside some other string we use in operator;
to filter items we use if-clause in the dictionary comprehension.
See also:
about dictionary comprehensions
about operators in and not in

want to find a matching variable from multi key possibly tuples in dict and print the value in python

How can i search a variable from a multi key dict and get the respective value in python?
dict1 = {('1700','2700','3700'):'a3g3',('1502','1518'):'a2g3',('2600'):'a3g2'}
var = '1502'
output
should be a2g3
One way:
dict1 = {('1700','2700','3700'): 'a3g3',
('1502','1518'): 'a2g3',
('2600'): 'a3g2'}
print(next(v for k, v in dict1.items() if '1502' in k))
# a2g3
List comprehension is good approach ,
Here is Filter approach just for fun :
You can filter the result :
dict1 = {('1700','2700','3700'):'a3g3',('1502','1518'):'a2g3',('2600'):'a3g2'}
var = '1502'
print(dict1[list(filter(lambda x:var in x,dict1.keys()))[0]])
output:
a2g3
Just iterate over the keys and find
print([dict1[i] for i in dict1.keys() if var in i])

Python: Why does the dict.fromkeys method not produce a working dicitonary

I had the following dictionary:
ref_range = range(0,100)
aas = list("ACDEFGHIKLMNPQRSTVWXY*")
new_dict = {}
new_dict = new_dict.fromkeys(ref_range,{k:0 for k in aas})
Then I added a 1 to a specific key
new_dict[30]['G'] += 1
>>>new_dict[30]['G']
1
but
>>>new_dict[31]['G']
1
What is going on here? I only incremented the nested key 30, 'G' by one.
Note: If I generate the dictionary this way:
new_dict = {}
for i in ref_range:
new_dict[i] = {a:0 for a in aas}
Everything behaves fine. I think this is a similar question here, but I wanted to know a bit about why this happening rather than how to solve it.
fromkeys(S, v) sets all of the keys in S to the same value v. Meaning that all of the keys in your dictionary new_dict refer to the same dictionary object, not to their own copies of that dictionary.
To set each to a different dict object you cannot use fromkeys. You need to just set each key to a new dict in a loop.
Besides what you have you could also do
{i: {a: 0 for a in aas} for i in ref_range}

Refactoring with python dictionary comprehension

I have 2 dictionary which contain the same keys but the value pairs are different. Let's make dictA and dictB represent the two dictionaries in question.
dictA = {'key1':'Joe', 'key2':'Bob'}
dictB = {'key1':'Smith', 'key2':'Johnson'}
Currently, I am creating a new dictionary based the common occurring keys through a nested if statement. In doing so, the values that share a key are contained within a list, in the new dictionary. See this done below:
dictAB = {} # Create a new dictionary
# Create a list container for dictionary values
for key in dictA.keys():
dictAB[key] = []
# Iterate through keys in both dictionaries
# Find matching keys and append the respective values to the list container
for key, value in dictA.iteritems():
for key2, value2 in dictB.iteritems():
if key == key2:
dictAB[key].append(value)
dictAB[key].append(value2)
else:
pass
How can this be made into a more clean structure using python dictionary comprehension?
Use sets or key views (python 2.7):
dictAB = {k: [dictA[k], dictB[k]] for k in dictA.viewkeys() & dictB.viewkeys()}
Before 2.7:
dictAB = dict((k, [dictA[k], dictB[k]]) for k in set(dictA) & set(dictB))
In python 3, you can use the .keys method for such operations directly, as they are implemented as views:
dictAB = {k: [dictA[k], dictB[k]] for k in dictA.keys() & dictB.keys()}
Demo (python 2.7):
>>> dictA = {'key1':'Joe', 'key2':'Bob'}
>>> dictB = {'key1':'Smith', 'key2':'Johnson'}
>>> dictAB = {k: [dictA[k], dictB[k]] for k in dictA.viewkeys() & dictB.viewkeys()}
>>> print dictAB
{'key2': ['Bob', 'Johnson'], 'key1': ['Joe', 'Smith']}
The & operator on either two sets or on a dict view creates the intersection of both sets; all keys that are present in both sets.
By using an intersection of the keys, this code will work even if either dictA or dictB has keys that do not appear in the other dictionary. If you are absolutely sure the keys will always match, you could just iterate over either dict directly without the intersection:
dictAB = {k: [dictA[k], dictB[k]] for k in dictA}
dictAB = { key: [dictA[key],dictB[key]] for key in dictA if key in dictB }

index python dictionary by value [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Inverse dictionary lookup - Python
Is there a built in way to index a dictionary by value in Python.
e.g. something like:
dict = {'fruit':'apple','colour':'blue','meat':'beef'}
print key where dict[key] == 'apple'
or:
dict = {'fruit':['apple', 'banana'], 'colour':'blue'}
print key where 'apple' in dict[key]
or do I have to manually loop it?
You could use a list comprehension:
my_dict = {'fruit':'apple','colour':'blue','meat':'beef'}
print [key for key, value in my_dict.items() if value == 'apple']
The code above is doing almost exactly what said you want:
print key where dict[key] == 'apple'
The list comprehension is going through all the key, value pairs given by your dictionary's items method, and making a new list of all the keys where the value is 'apple'.
As Niklas pointed out, this does not work when your values could potentially be lists. You have to be careful about just using in in this case since 'apple' in 'pineapple' == True. So, sticking with a list comprehension approach requires some type checking. So, you could use a helper function like:
def equals_or_in(target, value):
"""Returns True if the target string equals the value string or,
is in the value (if the value is not a string).
"""
if isinstance(target, str):
return target == value
else:
return target in value
Then, the list comprehension below would work:
my_dict = {'fruit':['apple', 'banana'], 'colour':'blue'}
print [key for key, value in my_dict.items() if equals_or_in('apple', value)]
You'll have to manually loop it, but if you'll need the lookup repeatedly this is a handy trick:
d1 = {'fruit':'apple','colour':'blue','meat':'beef'}
d1_rev = dict((v, k) for k, v in d1.items())
You can then use the reverse dictionary like this:
>>> d1_rev['blue']
'colour'
>>> d1_rev['beef']
'meat'
Your requirements are more complex than you realize:
You need to handle both list values and plain values
You don't actually need to get back a key, but a list of keys
You could solve this in two steps:
normalize the dict so that every value is a list (every plain value becomes a single-element)
build a reverse dictionary
The following functions will solve this:
from collections import defaultdict
def normalize(d):
return { k:(v if isinstance(v, list) else [v]) for k,v in d.items() }
def build_reverse_dict(d):
res = defaultdict(list)
for k,values in normalize(d).items():
for x in values:
res[x].append(k)
return dict(res)
To be used like this:
>>> build_reverse_dict({'fruit':'apple','colour':'blue','meat':'beef'})
{'blue': ['colour'], 'apple': ['fruit'], 'beef': ['meat']}
>>> build_reverse_dict({'fruit':['apple', 'banana'], 'colour':'blue'})
{'blue': ['colour'], 'apple': ['fruit'], 'banana': ['fruit']}
>>> build_reverse_dict({'a':'duplicate', 'b':['duplicate']})
{'duplicate': ['a', 'b']}
So you just build up the reverse dictionary once and then lookup by value and get back a list of keys.

Categories

Resources