I want to use the items in a list as dictionary keys to find a value in nested dictionaries.
For example, given the following list:
keys = ['first', 'second', 'third']
I want to do:
result = dictionary[keys[0]][keys[1]][keys[2]]
Which would be the equivalent of:
result = dictionary['first']['second']['third']
But I don't know how many items will be in the keys list beforehand (except that it will always have at least 1).
Iteratively go into the subdictionaries.
result = dictionary
for key in keys:
result = result[key]
print(result)
A simple for-loop will work:
result = dictionary[keys[0]] # Access the first level (which is always there)
for k in keys[1:]: # Step down through any remaining levels
result = result[k]
Demo:
>>> dictionary = {'first': {'second': {'third': 123}}}
>>> keys = ['first', 'second', 'third']
>>> result = dictionary[keys[0]]
>>> for k in keys[1:]:
... result = result[k]
...
>>> result
123
>>>
Related
Example code:
my_dict = {'ABC':'Apple','DEF':'Mango','GHI':'Pear','JKL':'Orange','MNO':'Plum'}
lst_x = ['DEF','GHI']
Expected result:
['Mango', 'Pear']
You can retrieve multiple keys at once, by using operator.itemgetter:
from operator import itemgetter
my_dict = {'ABC':'Apple','DEF':'Mango','GHI':'Pear','JKL':'Orange','MNO':'Plum'}
lst_x = ['DEF','GHI']
# in case, if there's a chance, that lst_x would get some of the keys, that are not in my_dict - add the below line:
# lst_x=set(lst_x).intersection(set(my_dict.keys()))
res=itemgetter(*lst_x)(my_dict)
Outputs:
>>> res
('Mango', 'Pear')
You can use a simple loop, ask if there is a key with the same value and print it, for example:
my_dict = {'ABC':'Apple','DEF':'Mango','GHI':'Pear','JKL':'Orange','MNO':'Plum'}
lst = ['ABC','DEF','GHI','JKL','MNO']
for key in lst:
if key in my_dict.keys():
print(key, '->' , my_dict[key])
>>> ABC -> Apple
>>> DEF -> Mango
>>> GHI -> Pear
>>> JKL -> Orange
>>> MNO -> Plum
One approach would be to use a list comprehension to construct the requested list.
Essentially we iterate through the list in the outer loop, and through the dictionary in the inner loop and then we compare the list value with the keyfrom the dictionary, and should we have a match, then we save the value of the associated key in the new output list.
This code snippet below works as described above:
my_dict = {'ABC':'Apple','DEF':'Mango','GHI':'Pear','JKL':'Orange','MNO':'Plum'}
lst_x = ['DEF','GHI']
out = [value for element in lst_x for key, value in my_dict.items() if element == key]
print(out)
When run it prints:
['Mango', 'Pear']
I personally don't believe in giving outright answers so I will give you a hint:
// for x in lst:
// if x in dictionary then
// lst_x.append(x)
I believe that should be enough for you to figure out the rest.
I have a dictionary contains lists of values and a list:
dict1={'first':['hi','nice'], 'second':['night','moon']}
list1= [ 'nice','moon','hi']
I want to compare the value in the dictionary with the list1 and make a counter for the keys if the value of each key appeared in the list:
the output should like this:
first 2
second 1
here is my code:
count = 0
for list_item in list1:
for dict_v in dict1.values():
if list_item.split() == dict_v:
count+= 1
print(dict.keys,count)
any help? Thanks in advance
I would make a set out of list1 for the O(1) lookup time and access to the intersection method. Then employ a dict comprehension.
>>> dict1={'first':['hi','nice'], 'second':['night','moon']}
>>> list1= [ 'nice','moon','hi']
>>>
>>> set1 = set(list1)
>>> {k:len(set1.intersection(v)) for k, v in dict1.items()}
{'first': 2, 'second': 1}
intersection accepts any iterable argument, so creating sets from the values of dict1 is not necessary.
You can use the following dict comprehension:
{k: sum(1 for i in l if i in list1) for k, l in dict1.items()}
Given your sample input, this returns:
{'first': 2, 'second': 1}
You can get the intersection of your list and the values of dict1 using sets:
for key in dict1.keys():
count = len(set(dict1[key]) & set(list1))
print("{0}: {1}".format(key,count))
While brevity can be great, I thought it would be good to also provide an example that is as close to the OPs original code as possible:
# notice conversion to set for O(1) lookup
# instead of O(n) lookup where n is the size of the list of desired items
dict1={'first':['hi','nice'], 'second':['night','moon']}
set1= set([ 'nice','moon','hi'])
for key, values in dict1.items():
counter = 0
for val in values:
if val in set1:
counter += 1
print key, counter
Using collections.Counter
from collections import Counter
c = Counter(k for k in dict1 for i in list1 if i in dict1[k])
# Counter({'first': 2, 'second': 1})
The most simplest and basic approach would be:
dict1={'first':['hi','nice'], 'second':['night','moon']}
list1= [ 'nice','moon','hi']
listkeys=list(dict1.keys())
listvalues=list(dict1.values())
for i in range(0,len(listvalues)):
ctr=0
for j in range(0,len(listvalues[i])):
for k in range(0,len(list1)):
if list1[k]==listvalues[i][j]:
ctr+=1
print(listkeys[i],ctr)
Hope it helps.
Say I have a dictionary with many items that have the same values; for example:
dict = {'hello':'a', 'goodbye':'z', 'bonjour':'a', 'au revoir':'z', 'how are you':'m'}
How would I split the dictionary into dictionaries (in this case, three dictionaries) with the same values? In the example, I want to end up with this:
dict1 = {'hello':'a', 'bonjour':'a'}
dict2 = {'goodbye':'z', 'au revoir':'z'}
dict3 = {'how are you':'m'}
You can use itertools.groupby to collect by the common values, then create dict objects for each group within a list comprehension.
>>> from itertools import groupby
>>> import operator
>>> by_value = operator.itemgetter(1)
>>> [dict(g) for k, g in groupby(sorted(d.items(), key = by_value), by_value)]
[{'hello': 'a', 'bonjour': 'a'},
{'how are you': 'm'},
{'goodbye': 'z', 'au revoir': 'z'}]
Another way without importing any modules is as follows:
def split_dict(d):
unique_vals = list(set(d.values()))
split_dicts = []
for i in range(len(unique_vals)):
unique_dict = {}
for key in d:
if d[key] == unique_vals[i]:
unique_dict[key] = d[key]
split_dicts.append(unique_dict)
return split_dicts
For each unique value in the input dictionary, we create a dictionary and add the key values pairs from the input dictionary where the value is equal to that value. We then append each dictionary to a list, which is finally returned.
I trying to print out a dictionary in Python:
Dictionary = {"Forename":"Paul","Surname":"Dinh"}
for Key,Value in Dictionary.iteritems():
print Key,"=",Value
Although the item "Forename" is listed first, but dictionaries in Python seem to be sorted by values, so the result is like this:
Surname = Dinh
Forename = Paul
How to print out these with the same order in code or the order when items are appended in (not sorted by values nor by keys)?
You can use a list of tuples (or list of lists). Like this:
Arr= [("Forename","Paul"),("Surname","Dinh")]
for Key,Value in Arr:
print Key,"=",Value
Forename = Paul
Surname = Dinh
you can make a dictionary out of this with:
Dictionary=dict(Arr)
And the correctly sorted keys like this:
keys = [k for k,v in Arr]
Then do this:
for k in keys: print k,Dictionary[k]
but I agree with the comments on your question: Would it not be easy to sort the keys in the required order when looping instead?
EDIT: (thank you Rik Poggi), OrderedDict does this for you:
od=collections.OrderedDict(Arr)
for k in od: print k,od[k]
First of all dictionaries are not sorted at all nor by key, nor by value.
And basing on your description. You actualy need collections.OrderedDict module
from collections import OrderedDict
my_dict = OrderedDict([("Forename", "Paul"), ("Surname", "Dinh")])
for key, value in my_dict.iteritems():
print '%s = %s' % (key, value)
Note that you need to instantiate OrderedDict from list of tuples not from another dict as dict instance will shuffle the order of items before OrderedDict will be instantiated.
You can use collections.OrderedDict. It's available in python2.7 and python3.2+.
This may meet your need better:
Dictionary = {"Forename":"Paul","Surname":"Dinh"}
KeyList = ["Forename", "Surname"]
for Key in KeyList:
print Key,"=",Dictionary[Key]
'but dictionaries in Python are sorted by values' maybe I'm mistaken here but what game you that ideea? Dictionaries are not sorted by anything.
You would have two solutions, either keep a list of keys additional to the dictionary, or use a different data structure like an array or arrays.
I wonder if it is an ordered dict that you want:
>>> k = "one two three four five".strip().split()
>>> v = "a b c d e".strip().split()
>>> k
['one', 'two', 'three', 'four', 'five']
>>> v
['a', 'b', 'c', 'd', 'e']
>>> dx = dict(zip(k, v))
>>> dx
{'four': 'd', 'three': 'c', 'five': 'e', 'two': 'b', 'one': 'a'}
>>> for itm in dx:
print(itm)
four
three
five
two
one
>>> # instantiate this data structure from OrderedDict class in the Collections module
>>> from Collections import OrderedDict
>>> dx = OrderedDict(zip(k, v))
>>> for itm in dx:
print(itm)
one
two
three
four
five
A dictionary created using the OrderdDict preserves the original insertion order.
Put another way, such a dictionary iterates over the key/value pairs according to the order in which they were inserted.
So for instance, when you delete a key and then add the same key again, the iteration order is changes:
>>> del dx['two']
>>> for itm in dx:
print(itm)
one
three
four
five
>>> dx['two'] = 'b'
>>> for itm in dx:
print(itm)
one
three
four
five
two
As of Python 3.7, regular dicts are guaranteed to be ordered, so you can just do
Dictionary = {"Forename":"Paul","Surname":"Dinh"}
for Key,Value in Dictionary.items():
print(Key,"=",Value)
[{'id':44}, {'name':'alexa'},{'color':'blue'}]
I want to select whatever in the list that is "id".
Basically, I want to print 44, since that's "id" in the list.
That's a weird data structure... A list of one item dictionaries.
key = 'id'
l = [{'id':44}, {'name':'alexa'},{'color':'blue'}]
print [ x[key] for x in l if key in x ][0]
Assuming you can rely on key being present precisely once...
Maybe you should just convert the list into a dictionary first:
key = 'id'
l = [{'id':44}, {'name':'alexa'},{'color':'blue'}]
d = {}
for x in l:
d.update(x)
print d[key]
All the other answers solve your problem, I am just suggesting an alternative way of going about doing this.
Instead of having a list of dicts where you query on the key and have to iterate over all list items to get values, just use a dict of lists. Each key would map to a list of values (or just one value if all your dicts had distinct sets of keys).
So,
data=[{'id':44}, {'name':'alexa'},{'color':'blue'}]
becomes
data={'id':[44], 'name':['alexa'], 'color':['blue']}
and you can neatly access the value for 'id' using data['id'] (or data['id'][0] if you only need one value).
If all your keys are distinct across the dicts (as in your example) you don't even have to have lists of values.
data={'id':44, 'name':'alexa', 'color':'blue'}
Not only does this make your code cleaner, it also speeds up your queries which no longer have to iterate over a list.
Probably this is the best solution:
>>> L = [{'id':44}, {'name':'alexa'},{'color':'blue'}]
>>> newd = {}
>>> for d in L:
... newd.update(d)
>>> newd['id']
44
You could do something like this:
>>> KEY = 'id'
>>>
>>> my_list = [{'id':44}, {'name':'alexa'},{'color':'blue'}]
>>> my_ids = [x[KEY] for x in my_list if KEY in x]
>>> print my_ids
[44]
Which is obviously a list of the values you want. You can then print them as required.
>>> from itertools import dropwhile
>>> def find_value(l, key):
... return dropwhile(lambda x: key not in x, l).next()[key]
>>> find_value([{'id':44}, {'name':'alexa'},{'color':'blue'}], "id")
This will do a linear search, but only until the element is found.
If you want to have proper error handling, use:
def find_value(l, key):
try:
return dropwhile(lambda x: key not in x, l).next()[key]
except StopIteration:
raise ValueError(key)
>>> L = [{'id':44}, {'name':'alexa'},{'color':'blue'}]
>>> newd=dict(d.items()[0] for d in L)
>>> newd['id']
44