How to Create Nested Dictionary in Python with 3 lists - python

Let us Suppose, I have created 3 lists and I want to create a dictionary for it. e.g.
a= ['A', 'B', 'C', 'D']
b =[1, 2, 3, 4]
c = [9, 8, 7, 6]
Now What I want is to create a dictionary like this:
{'A':{'1' :'9'} , 'B':{'2':'8'}, 'C':{'3':'7'} , 'D':{'4':'6'}}
is it possible, Can Someone Help me on this?

You can create the dictionary from zip-ed lists and convert the int values to strings - if I understood your question proper
dct = {x: {str(y): str(z)} for x, y, z in zip(a,b,c)}
Output:
{'A': {'1': '9'}, 'C': {'3': '7'}, 'B': {'2': '8'}, 'D': {'4': '6'}}

You can also use map() here:
a = ['A', 'B', 'C', 'D']
b = [1, 2, 3, 4]
c = [9, 8, 7, 6]
dct = dict(map(lambda x, y, z : (x, {str(y): str(z)}), a, b, c))
print(dct)
Which outputs:
{'A': {'1': '9'}, 'B': {'2': '8'}, 'C': {'3': '7'}, 'D': {'4': '6'}}

{ a[x]: {b[x]: c[x]} for x in range(len(a))}
or if you really mean it:
{ a[x]: {str(b[x]): str(c[x])} for x in range(len(a))}

a = ['A', 'B', 'C', 'D'] # don't forget the quotation marks
b = [1, 2, 3, 4]
c = [9, 8, 7, 6]
res = dict()
for i, index_a in enumerate(a):
res[index_a] = {str(b[i]): c[i]}
Edit: Alternatively with list comprehension (mainly for the voters in here, as it's advanced python and harder to understand):
res = dict((a[i], {str(b[i]): c[i]}) for i in range(len(a)))

You can try this:
a= ['A', 'B', 'C', 'D']
b =[1, 2, 3, 4]
c = [9, 8, 7, 6]
new_data = dict([[a, dict([map(str, i)])] for a, i in zip(a, zip(b, c))])
Output:
{'A': {'1': '9'}, 'C': {'3': '7'}, 'B': {'2': '8'}, 'D': {'4': '6'}}
Or
new_data = dict(zip(a, map(lambda x:dict([x]), zip(map(str, b), map(str, c)))))

Assuming what you want is to have a be keys in the outer dictionary, and b and c the key and value element of the inner dicts:
d = {k: {x: y} for k, x, y in zip(a, b, c)}
Update:
However, in your example x and y are strings, so if that's what you want:
d = {k: {str(x): str(y)} for k, x, y in zip(a, b, c)}

Are you looking for something like this ?
a= ['A', 'B', 'C', 'D']
b =[1, 2, 3, 4]
c = [9, 8, 7, 6]
new_dict={}
set(map(lambda x,y,z:(new_dict.__setitem__(x,{y,z})),a,b,c))
print(new_dict)
output:
{'D': {4, 6}, 'A': {9, 1}, 'B': {8, 2}, 'C': {3, 7}}

Related

grouping values based on date and time [duplicate]

I want to merge list of dictionaries in python. The number of dictionaries contained inside the list is not fixed and the nested dictionaries are being merged on both same and different keys. The dictionaries within the list do not contain nested dictionary. The values from same keys can be stored in a list.
My code is:
list_of_dict = [{'a': 1, 'b': 2, 'c': 3}, {'a': 3, 'b': 5}, {'k': 5, 'j': 5}, {'a': 3, 'k': 5, 'd': 4}, {'a': 3} ...... ]
output = {}
for i in list_of_dict:
for k,v in i.items():
if k in output:
output[k].append(v)
else:
output[k] = [v]
Is there a shorter and faster way of implementing this?
I am actually trying to implement the most fast way of doing this because the list of dictionary is very large and then there are lots of rows with such data.
One way using collections.defaultdict:
from collections import defaultdict
res = defaultdict(list)
for d in list_of_dict:
for k, v in d.items():
res[k].append(v)
Output:
defaultdict(list,
{'a': [1, 3, 3, 3],
'b': [2, 5],
'c': [3],
'k': [5, 5],
'j': [5],
'd': [4]})
items() is a dictionary method, but list_of_dict is a list. You need a nested loop so you can loop over the dictionaries and then loop over the items of each dictionary.
ou = {}
for d in list_of_dict:
for key, value in d.items():
output.setdefault(key, []).append(value)
another shorten version can be,
list_of_dict = [{'a': 1, 'b': 2, 'c': 3}, {'a': 3, 'b': 5}, {'k': 5, 'j': 5}, {'a': 3, 'k': 5, 'd': 4}, {'a': 3}]
output = {
k: [d[k] for d in list_of_dict if k in d]
for k in set().union(*list_of_dict)
}
print(output)
{'d': [4], 'k': [5, 5], 'a': [1, 3, 3, 3], 'j': [5], 'c': [3], 'b': [2, 5]}
Python 3.9+ you can use the merge operator for this.
def merge_dicts(dicts):
result = dict()
for _dict in dicts:
result |= _dict
return result
One of the shortest way would be to
prepare a list/set of all the keys from all the dictionaries
and call that key on all the dictionary in the list.
list_of_dict = [{'a': 1, 'b': 2, 'c': 3}, {'a': 3, 'b': 5}, {'k': 5, 'j': 5}, {'a': 3, 'k': 5, 'd': 4}, {'a': 3}]
# prepare a list/set of all the keys from all the dictionaries
# method 1: use sum
all_keys = sum([[a for a in x.keys()] for x in list_of_dict], [])
# method 2: use itertools
import itertools
all_keys = list(itertools.chain.from_iterable(list_of_dict))
# method 3: use union of the set
all_keys = set().union(*list_of_dict)
print(all_keys)
# ['a', 'b', 'c', 'a', 'b', 'k', 'j', 'a', 'k', 'd', 'a']
# convert the list to set to remove duplicates
all_keys = set(all_keys)
print(all_keys)
# {'a', 'k', 'c', 'd', 'b', 'j'}
# now merge the dictionary
merged = {k: [d.get(k) for d in list_of_dict if k in d] for k in all_keys}
print(merged)
# {'a': [1, 3, 3, 3], 'k': [5, 5], 'c': [3], 'd': [4], 'b': [2, 5], 'j': [5]}
In short:
all_keys = set().union(*list_of_dict)
merged = {k: [d.get(k) for d in list_of_dict if k in d] for k in all_keys}
print(merged)
# {'a': [1, 3, 3, 3], 'k': [5, 5], 'c': [3], 'd': [4], 'b': [2, 5], 'j': [5]}

How to change the value of a key in a 2d dictionary while looping

I want to change the value of a key inside a 2D dictionary while looping, but the program is behaving in a way I did not expect.
So first I initiated my 2D dictionary:
dict1 = dict()
dict2 = dict()
list = ['a', 'b', 'c']
list2 = ['A', 'B', 'C']
for i in list2:
dict1[i] = []
for i in list:
dict2[i] = dict1
Now I created a nested loop to change the key by appending a value to a list:
count = 0
for i in range(3):
for j in range(3):
dict2[list[i]][list2[j]].append(count)
count += 1
print(dict2)
The outcome is as follows:
{'a': {'A': [0, 3, 6], 'B': [1, 4, 7], 'C': [2, 5, 8]}, 'b': {'A': [0, 3, 6], 'B': [1, 4, 7], 'C': [2, 5, 8]}, 'c': {'A': [0, 3, 6], 'B': [1, 4, 7], 'C': [2, 5, 8]}}
whereas I expected to see this:
{'a': {'A': [0], 'B': [1], 'C': [2]}, 'b': {'A': [3], 'B': [4], 'C': [5]}, 'c': {'A': [6], 'B': [7], 'C': [8]}}
Why is the code behaving in this way and what can I change to get the outcome that I'm looking for?
Thanks!
What #darrylg says in the comment is correct. You can also combine a number of the for-loops you are using, e.g.:
keys1 = ['a', 'b', 'c']
keys2 = ['A', 'B', 'C']
dict2 = {k1: {k2: [] for k2 in keys2} for k1 in keys1}
for count, (i, j) in enumerate((i, j) for i in range(3) for j in range(3)):
dict2[keys1[i]][keys2[j]].append(count)
or, maybe better:
for count, (k1, k2) in enumerate((k1, k2) for k1 in keys1 for k2 in keys2):
dict2[k1][k2].append(count)
or perhaps, using itertools.product:
import itertools
for count, (k1, k2) in enumerate(itertools.product(keys1, keys2)):
dict2[k1][k2].append(count)
you could write it as a one-liner, although I'd strongly suggest not doing this :-) :
dict2 = (count := -1) and {k1: {k2: [count := count+1] for k2 in 'ABC'} for k1 in 'abc'}
which given:
import pprint
pprint.pprint(dict2)
will print:
{'a': {'A': [0], 'B': [1], 'C': [2]},
'b': {'A': [3], 'B': [4], 'C': [5]},
'c': {'A': [6], 'B': [7], 'C': [8]}}

How to merge list of dictionaries in python in shortest and fastest way possible?

I want to merge list of dictionaries in python. The number of dictionaries contained inside the list is not fixed and the nested dictionaries are being merged on both same and different keys. The dictionaries within the list do not contain nested dictionary. The values from same keys can be stored in a list.
My code is:
list_of_dict = [{'a': 1, 'b': 2, 'c': 3}, {'a': 3, 'b': 5}, {'k': 5, 'j': 5}, {'a': 3, 'k': 5, 'd': 4}, {'a': 3} ...... ]
output = {}
for i in list_of_dict:
for k,v in i.items():
if k in output:
output[k].append(v)
else:
output[k] = [v]
Is there a shorter and faster way of implementing this?
I am actually trying to implement the most fast way of doing this because the list of dictionary is very large and then there are lots of rows with such data.
One way using collections.defaultdict:
from collections import defaultdict
res = defaultdict(list)
for d in list_of_dict:
for k, v in d.items():
res[k].append(v)
Output:
defaultdict(list,
{'a': [1, 3, 3, 3],
'b': [2, 5],
'c': [3],
'k': [5, 5],
'j': [5],
'd': [4]})
items() is a dictionary method, but list_of_dict is a list. You need a nested loop so you can loop over the dictionaries and then loop over the items of each dictionary.
ou = {}
for d in list_of_dict:
for key, value in d.items():
output.setdefault(key, []).append(value)
another shorten version can be,
list_of_dict = [{'a': 1, 'b': 2, 'c': 3}, {'a': 3, 'b': 5}, {'k': 5, 'j': 5}, {'a': 3, 'k': 5, 'd': 4}, {'a': 3}]
output = {
k: [d[k] for d in list_of_dict if k in d]
for k in set().union(*list_of_dict)
}
print(output)
{'d': [4], 'k': [5, 5], 'a': [1, 3, 3, 3], 'j': [5], 'c': [3], 'b': [2, 5]}
Python 3.9+ you can use the merge operator for this.
def merge_dicts(dicts):
result = dict()
for _dict in dicts:
result |= _dict
return result
One of the shortest way would be to
prepare a list/set of all the keys from all the dictionaries
and call that key on all the dictionary in the list.
list_of_dict = [{'a': 1, 'b': 2, 'c': 3}, {'a': 3, 'b': 5}, {'k': 5, 'j': 5}, {'a': 3, 'k': 5, 'd': 4}, {'a': 3}]
# prepare a list/set of all the keys from all the dictionaries
# method 1: use sum
all_keys = sum([[a for a in x.keys()] for x in list_of_dict], [])
# method 2: use itertools
import itertools
all_keys = list(itertools.chain.from_iterable(list_of_dict))
# method 3: use union of the set
all_keys = set().union(*list_of_dict)
print(all_keys)
# ['a', 'b', 'c', 'a', 'b', 'k', 'j', 'a', 'k', 'd', 'a']
# convert the list to set to remove duplicates
all_keys = set(all_keys)
print(all_keys)
# {'a', 'k', 'c', 'd', 'b', 'j'}
# now merge the dictionary
merged = {k: [d.get(k) for d in list_of_dict if k in d] for k in all_keys}
print(merged)
# {'a': [1, 3, 3, 3], 'k': [5, 5], 'c': [3], 'd': [4], 'b': [2, 5], 'j': [5]}
In short:
all_keys = set().union(*list_of_dict)
merged = {k: [d.get(k) for d in list_of_dict if k in d] for k in all_keys}
print(merged)
# {'a': [1, 3, 3, 3], 'k': [5, 5], 'c': [3], 'd': [4], 'b': [2, 5], 'j': [5]}

how to identify relationship/mapping between the two list in python?

I have created two list.
list1= [a,b,c,a,d]
list2=[1,2,3,4,5]
I want to find relationship between this two list based on index position i.e
In list1 a is repeated 2 times index 0,3 .in list2 index 0,3 values are 1 ,4 the relation is a one to many is a:{1,4}
next b not repeated in list 1 and it index is 1 and list2 index 1 value is 2 ,the relation is one to one b:{2}
my expected output will be {a:{1,4},b:{2},c:{3},d:{5}}
I'd use a defaultdict:
from collections import defaultdict
list1 = ['a', 'b', 'c', 'a', 'd']
list2 = [1, 2, 3, 4, 5]
result = defaultdict(set)
for value1, value2, in zip(list1, list2):
result[value1].add(value2)
print(dict(result))
outputs
{'a': {1, 4}, 'b': {2}, 'c': {3}, 'd': {5}}
You can use a combination of dictionary and list comprehension to do this:
{x: [list2[i] for i, j in enumerate(list1) if j == x] for x in list1}
output:
{'a': [1, 4], 'b': [2], 'c': [3], 'd': [5]}
a = ['a', 'b', 'c', 'a', 'd']
b = [1, 2, 3, 4, 5]
ret = {}
for idx, _a in enumerate(a):
value = ret.get(_a, ret.setdefault(_a, []))
value.append(b[idx])
And ret will be the output
Option is to zip the two lists:
L = list(zip(list1, list2))
Result:
[('a', 1), ('b', 2), ('c', 3), ('a', 4), ('d', 5)]
Use it to create a dictionary with sets as values:
D ={}
for key in L:
if key[0] not in D:
D[key[0]] = {key[1]}
else:
D[key[0]].add(key[1])
I would not do it this way in real code, but this approach is mildly entertaining and perhaps educational.
from collections import defaultdict
from itertools import groupby
from operator import itemgetter
xs = ['a', 'b', 'c', 'a', 'd']
ys = [1, 2, 3, 4, 5]
d = {
x : set(y for _, y in group)
for x, group in groupby(sorted(zip(xs, ys)), key = itemgetter(0))
}
print(d) # {'a': {1, 4}, 'b': {2}, 'c': {3}, 'd': {5}}
It's not from pure python, as this question tagged with pandas I tried this way.
Option-1
df=pd.DataFrame({'l1':list1,'l2':list2})
res1=df.groupby('l1').apply(lambda x:x.l2.values.tolist()).to_dict()
Option-2
print df.groupby('l1')['l2'].unique().to_dict()
Output:
{'a': [1, 4], 'c': [3], 'b': [2], 'd': [5]}

Dictionaries and listing positions of word in a list

I need to take a list and use a dictionary to catalogue where a particular item occurs in a list, as an example:
L = ['a', 'b', 'c', 'b', 'c', 'a', 'e']
the dictionary needs to contain the following:
D = {'a': 0, 5 , 'b': 1, 3 , 'c': 2, 4 , 'e': 6}
However if I use what I wrote:
for i in range(len(word_list)):
if D.has_key('word_list[i]') == False:
D['word_list[i]'] = i
else:
D[word_list[i]] += i
Then I get a KeyError for a certain word and I don't understand why I should be getting an error.
if D.has_key('word_list[i]') == False:
Uh, what?
At the very least, you should drop the quotes:
if D.has_key(word_list[i]) == False:
But you're also misusing a number of Python structures:
Why are summing up the indices?
Why are you comparing to False?
Shouldn't you be using setdefault
Like this:
for i in range(len(word_list)):
D.setdefault(word_list[i], []).append(i)
I modified you solution a bit to work
word_list = ['a', 'b', 'c', 'b', 'c', 'a', 'e']
dict = {'a': [], 'b': [], 'c': [], 'e': []}
for i in range(len(word_list)):
if word_list[i] not in dict:
dict[word_list[i]] = [i]
else:
dict[word_list[i]].append(i)
Result
{'a': [0, 5], 'c': [2, 4], 'b': [1, 3], 'e': [6]}
I think this would be the shortest solution for your problem:
>>> from collections import defaultdict
>>> D = defaultdict(list)
>>> for i,el in enumerate(L):
D[el].append(i)
>>> D
defaultdict(<type 'list'>, {'a': [0, 5], 'c': [2, 4], 'b': [1, 3], 'e': [6]})
If you want to stick with dict, correcting your code I would came up with:
>>> D = {}
>>> for i,el in enumerate(L):
if el not in D:
D[el] = [i] #crate a new list
else:
D[el].append(i) #appending to the existing list
>>> D
{'a': [0, 5], 'c': [2, 4], 'b': [1, 3], 'e': [6]}
Also, there is a setdefault method in dict which can be used:
>>> D = {}
>>> for i,el in enumerate(L):
D.setdefault(el,[]).append(i)
>>> D
{'a': [0, 5], 'c': [2, 4], 'b': [1, 3], 'e': [6]}
But I prefer to use defaultdict from collections.

Categories

Resources