How to iterate over particular keys in a dict to get values - python

I have a large list containing many dictionaries. Within each dictionary I want to iterate over 3 particular keys and then dump into a new list. The keys are the same for each dict.
For example, I'd like to grab keys c, d, e from all the dicts in List below, output to List2.
List = [{'a':1, 'b':2, 'c':3, 'd':4, 'e':5, 'f':6...},
{'a':10, 'b':20, 'c':30, 'd':40, 'e':50, 'f':60...},
{'a':100, 'b':200, 'c':300, 'd':400, 'e':500, 'f':600...},]
List2 = [{'c':3, 'd':4, 'e':5},
{'c':30, 'd':40, 'e':50},
{'c':300, 'd':400, 'e':500}]

You can use a nested dict comprehension:
keys = ('c', 'd', 'e')
[{k: d[k] for k in keys} for d in List]
If those keys may be missing, you can use a dictionary view object (dict.viewkeys() in Python 2, dict.keys() in Python 3) to find an intersection to only include keys that are actually present:
keys = {'c', 'd', 'e'}
[{k: d[k] for k in d.viewkeys() & keys} for d in List]
Demo:
>>> List = [{'a':1, 'b':2, 'c':3, 'd':4, 'e':5, 'f':6},
... {'a':10, 'b':20, 'c':30, 'd':40, 'e':50, 'f':60},
... {'a':100, 'b':200, 'c':300, 'd':400, 'e':500, 'f':600}]
>>> keys = ('c', 'd', 'e')
>>> [{k: d[k] for k in keys} for d in List]
[{'c': 3, 'e': 5, 'd': 4}, {'c': 30, 'e': 50, 'd': 40}, {'c': 300, 'e': 500, 'd': 400}]
>>> List = [{'a':1, 'b':2, 'd':4, 'e':5, 'f':6},
... {'a':10, 'b':20, 'c':30, 'd':40, 'f':60},
... {'a':100, 'b':200, 'e':500, 'f':600}]
>>> keys = {'c', 'd', 'e'}
>>> [{k: d[k] for k in d.viewkeys() & keys} for d in List]
[{'e': 5, 'd': 4}, {'c': 30, 'd': 40}, {'e': 500}]

Try this code:
keys = ['c', 'd']
for dictionary in List1:
d = {}
for key in dictionary:
if key in keys:
d[key] = dictionary[key]
List2.append(d)

Related

merge a list of dicts by a certain key

I have a list which is composed of dict of same structure ,
sample = [{'a':1, 'b':2, 'c':3}, {'a':1, 'b':2, 'c':4}, {'a':2, 'b':2, 'c':5}, {'a':2, 'b':3, 'c':5}]
I want to combine them by key a, the out should be
[{'a': 1, 'd': [{'b':2, 'c':3}, {'b':2, 'c':4}]}, {'a': 2, 'd': [{'b':2, 'c':5}, {'b': 3, 'c':5}]}]
You can use itertools.groupby:
>>> from itertools import groupby
>>> result = []
>>> for key, group in groupby(sorted(sample, key=lambda x:x['a']), key=lambda x:x.pop('a')):
result.append({'a':key, 'd':[*group]})
>>> result
[{'a': 1, 'd': [{'b': 2, 'c': 3}, {'b': 2, 'c': 4}]},
{'a': 2, 'd': [{'b': 2, 'c': 5}, {'b': 3, 'c': 5}]}]
NOTE: You don't need sorted if it is guaranteed that the list of dicts come sorted by the value of key a.
Combine by key:
dict_list = [{'a':1, 'b':2, 'c':3}, {'a':1, 'b':2, 'c':4}, {'a':2, 'b':2, 'c':5}, {'a':2, 'b':3, 'c':5}]
new_dict = {}
for d in dict_list:
a = d.pop('a', None)
if new_dict.get(a):
new_dict[a].append(d)
else:
new_dict[a] = [d]
Convert to list:
final_list = [{'a': key, 'd': value} for key, value in new_dict.items()]
print(final_list)
[{'a': 1, 'd': [{'c': 3, 'b': 2}, {'c': 4, 'b': 2}]}, {'a': 2, 'd': [{'c': 5, 'b': 2}, {'c': 5, 'b': 3}]}]
sample = [{'a':1, 'b':2, 'c':3}, {'a':1, 'b':2, 'c':4}, {'a':2, 'b':2, 'c':5}, {'a':2, 'b':3, 'c':5}]
tmp = {}
for v in sample:
tmp.setdefault(v['a'], []).append(v)
del v['a']
out = [{'a': k, 'd': v} for k, v in tmp.items()]
from pprint import pprint
pprint(out)
Prints:
[{'a': 1, 'd': [{'b': 2, 'c': 3}, {'b': 2, 'c': 4}]},
{'a': 2, 'd': [{'b': 2, 'c': 5}, {'b': 3, 'c': 5}]}]
This may be a bit twisty code unfortunately, but it works:
from itertools import groupby
sample = [{'a':1, 'b':2, 'c':3},
{'a':1, 'b':2, 'c':4},
{'a':2, 'b':2, 'c':5},
{'a':2, 'b':3, 'c':5}]
main_key = "a"
print(
[{main_key:k,
"d": [{kk: vv for kk, vv in dct.items() if kk != main_key}
for dct in v]}
for k, v in groupby(sample, lambda d:d[main_key])]
)
gives:
[{'a': 1, 'd': [{'b': 2, 'c': 3}, {'b': 2, 'c': 4}]},
{'a': 2, 'd': [{'b': 2, 'c': 5}, {'b': 3, 'c': 5}]}]
(output slightly pretty-printed for readability)
An alternative solution using Pandas for your query.
import pandas as pd
sample = [{'a':1, 'b':2, 'c':3}, {'a':1, 'b':2, 'c':4}, {'a':2, 'b':2, 'c':5}, {'a':2, 'b':3, 'c':5}]
df=pd.DataFrame(sample)
This would create a DataFrame df using the above sample list. The next step would be to iterate through the GroupBy Object and create the output as required.
final_list=[]
for i, temp_df in df.groupby('a'):
temp_list=[]
for j in temp_df.index:
temp_list.append({'b':temp_df.loc[:,'b'][j],'c':temp_df.loc[:,'c'][j]})
final_list.append({'a':temp_df.loc[:,'a'][j],'d':temp_list})

How to "sort" a dictionary by number of occurrences of a key?

I have a dictionary of values that gives the number of occurrences of a value in a list. How can I return a new dictionary that divides the former dictionary into separate dictionaries based on the value?
In other words, I want to sort this dictionary:
>>> a = {'A':2, 'B':3, 'C':4, 'D':2, 'E':3}
to this one.
b = {2: {'A', 'D'}, 3: {'B', 'E'}, 4: {'C'}}
How do I approach the problem?
from collections import defaultdict
a = {'A': 2, 'B': 3, 'C': 4, 'D': 2, 'E': 3}
b = defaultdict(set)
for k, v in a.items():
b[v].add(k)
This is what you'll get:
defaultdict(<class 'set'>, {2: {'D', 'A'}, 3: {'B', 'E'}, 4: {'C'}})
You can convert b to a normal dict afterwards with b = dict(b).
if you are a python beginner like me, you probably wanna try this
a = {'A': 2 , 'B': 3 , 'C' : 4 , 'D' : 2, 'E' : 3}
b = {}
for key in a:
lst = []
new_key = a[key]
if new_key not in b:
lst.append(key)
b[new_key] = lst
else:
b[new_key].append(key)
print(b)
It uses the mutable property of python dictionary to achieve the result you want.

Extracting key from the nested dictionary [duplicate]

So I have this block of code
dictionary = {
'key1': {'a': 1, 'b': 2, 'c': 10},
'key2': {'d': 1, 'e': 1, 'c': 11},
'key3': {'d': 2, 'b': 1, 'g': 12}}
and
list1 = (a,b,c)
What I want to do is run a loop that finds the maximums of all the items in the list and returns the key. So for example, the maximum of 'c' would return 'key2', the maximum of 'b' would return 'key1', etc.
So far I have
for value in list1:
m = max(dictionary, key=lambda v: dictionary[v][value])
print(m + "\n")
But this only works if the same subkey exists in all keys in the dictionary. Any ideas on what to do?
Use float('-inf') when the key is missing:
m = max(dictionary, key=lambda v: dictionary[v].get(value, float('-inf')))
Negative infinity is guaranteed to be smaller than any existing value in the dictionaries, ensuring that nested dictionaries with the specific key missing are ignored.
Demo:
>>> dictionary = {
... 'key1': {'a': 1, 'b': 2, 'c': 10},
... 'key2': {'d': 1, 'e': 1, 'c': 11},
... 'key3': {'d': 2, 'b': 1, 'g': 12}}
>>> list1 = ('a', 'b', 'c')
>>> for value in list1:
... print(value, max(dictionary, key=lambda v: dictionary[v].get(value, float('-inf'))))
...
a key1
b key1
c key2
However, it'll be more efficient if you looped over all your dictionary values just once instead:
maximi = dict.fromkeys(list1, (None, float('-inf')))
for key, nested in dictionary.items():
for k in nested.keys() & maximi: # intersection of keys
if maximi[k][0] is None or dictionary[maximi[k][0]][k] < nested[k]:
maximi[k] = (key, nested[k])
for value in list1:
print(value, maximi[value][0])
That's presuming you are using Python 3; in Python 2, replace .items() with .iteritems() and .keys() with .viewkeys().
Demo:
>>> maximi = dict.fromkeys(list1, (None, float('-inf')))
>>> for key, nested in dictionary.items():
... for k in nested.keys() & maximi: # intersection of keys
... if maximi[k][0] is None or dictionary[maximi[k][0]][k] < nested[k]:
... maximi[k] = (key, nested[k])
...
>>> maximi
{'a': ('key1', 1), 'b': ('key1', 2), 'c': ('key2', 11)}
>>> for value in list1:
... print(value, maximi[value][0])
...
a key1
b key1
c key2

Find Maximum Value in Nested Dictionary and return Key

So I have this block of code
dictionary = {
'key1': {'a': 1, 'b': 2, 'c': 10},
'key2': {'d': 1, 'e': 1, 'c': 11},
'key3': {'d': 2, 'b': 1, 'g': 12}}
and
list1 = (a,b,c)
What I want to do is run a loop that finds the maximums of all the items in the list and returns the key. So for example, the maximum of 'c' would return 'key2', the maximum of 'b' would return 'key1', etc.
So far I have
for value in list1:
m = max(dictionary, key=lambda v: dictionary[v][value])
print(m + "\n")
But this only works if the same subkey exists in all keys in the dictionary. Any ideas on what to do?
Use float('-inf') when the key is missing:
m = max(dictionary, key=lambda v: dictionary[v].get(value, float('-inf')))
Negative infinity is guaranteed to be smaller than any existing value in the dictionaries, ensuring that nested dictionaries with the specific key missing are ignored.
Demo:
>>> dictionary = {
... 'key1': {'a': 1, 'b': 2, 'c': 10},
... 'key2': {'d': 1, 'e': 1, 'c': 11},
... 'key3': {'d': 2, 'b': 1, 'g': 12}}
>>> list1 = ('a', 'b', 'c')
>>> for value in list1:
... print(value, max(dictionary, key=lambda v: dictionary[v].get(value, float('-inf'))))
...
a key1
b key1
c key2
However, it'll be more efficient if you looped over all your dictionary values just once instead:
maximi = dict.fromkeys(list1, (None, float('-inf')))
for key, nested in dictionary.items():
for k in nested.keys() & maximi: # intersection of keys
if maximi[k][0] is None or dictionary[maximi[k][0]][k] < nested[k]:
maximi[k] = (key, nested[k])
for value in list1:
print(value, maximi[value][0])
That's presuming you are using Python 3; in Python 2, replace .items() with .iteritems() and .keys() with .viewkeys().
Demo:
>>> maximi = dict.fromkeys(list1, (None, float('-inf')))
>>> for key, nested in dictionary.items():
... for k in nested.keys() & maximi: # intersection of keys
... if maximi[k][0] is None or dictionary[maximi[k][0]][k] < nested[k]:
... maximi[k] = (key, nested[k])
...
>>> maximi
{'a': ('key1', 1), 'b': ('key1', 2), 'c': ('key2', 11)}
>>> for value in list1:
... print(value, maximi[value][0])
...
a key1
b key1
c key2

Multiplying values from two different dictionaries together in Python

I have two separate dictionaries with keys and values that I would like to multiply together. The values should be multiplied just by the keys that they have.
i.e.
dict1 = {'a': 1, 'b': 2, 'c': 3}
dict2 = {'a': 15, 'b': 10, 'd': 17}
dict3 = dict.items() * dict.items()
print dict3
#### #dict3 should equal
{'a': 15, 'b': 20}
If anyone could help, that would be great.
Thanks!
You can use a dict comprehension:
>>> {k : v * dict2[k] for k, v in dict1.items() if k in dict2}
{'a': 15, 'b': 20}
Or, in pre-2.7 Python, the dict constructor in combination with a generator expression:
>>> dict((k, v * dict2[k]) for k, v in dict1.items() if k in dict2)
{'a': 15, 'b': 20}
From my telephone, so bit hard to type code. This should do the trick:
for key, value in dict1.iteritems():
if key in dict2:
dict3[key] = int(dict1[key]) * int(dict2[key])
dict1 = {'a': 1, 'b': 2, 'c': 3}
dict2 = {'a': 15, 'b': 10, 'd': 17}
def dict_mul(d1, d2):
d3 = dict()
for k in d1:
if k in d2:
d3[k] = d1[k] * d2[k]
return d3
print dict_mul(dict1, dict2)

Categories