Adding multiple new key-value pairs to a nested dictionary - python

I am new to python and I am trying to add key-value pairs to a nested dictionary. I tried a few approaches but I am not able to do it properly. This is the code that I have written:
dict1 = {}
dict1['name'] = {'domain': "something"}
i=0
while i < 10:
new = 'route'+str(i)
dict1['name']['routes'] = {new: {'bit_value': i}}
i = i+1
print(dict1)
This is the output I am getting:
{'name': {'domain': 'something', 'routes': {'route9': {'bit_value': 9}}}}
This is the kind of output that I want:
{'name': {'domain': 'something', 'routes': {'route1': {'bit_value': 1}, 'route2': {'bit_value': 2}, 'route3': {'bit_value': 3}, 'route4': {'bit_value': 4} ...}}}
I tried using this version as well, but it throws a Keyerror:
import collections
dict1 = collections.defaultdict(dict)
dict1['name'] = {'domain': "something"}
i = 0
while i < 10:
new = 'route'+str(i)
dict1['name']['routes'][new] = {'bit_value': i}
i = i+1
print(dict1)
Error message:
dict1['name']['routes'][new] = {'bit_value': i}
KeyError: 'routes'
It would be nice if this problem can be solved without changing into a for loop as the while loop will make it easier for me to integrate this with rest of the code that I have written. I would really appreciate if someone can help me.

First create the routes sub-dictionary, then insert items.
import collections
dict1 = collections.defaultdict(dict)
dict1['name'] = {'domain': "something"}
i = 0
##########
dict1['name']['routes'] = {}
##########
while i < 10:
new = 'route'+str(i)
dict1['name']['routes'][new] = {'bit_value': i}
i = i+1
print(dict1)

In your original solution, dict1['name']['routes'] is replaced with a new dictionary with only 1 key every time.
In your alternative version, dict1 is a defaultdict. So you can access e.g. dict1['randomkey'] without initializing it, but dict1['name'] or dict1['name']['routes'] is not a defaultdict. defaultdict(dict) means the values are normal dictionaries. If you need the values to be defaultdict as well, you can do defaultdict(defaultdict(dict))
But that's not what you want. You don't actually need to deal with default key values. You only need to initialize dict1['name']['routes'] once to a normal dictionary:
dict1 = {'name': {'domain': 'something', 'routes': {}}}
for i in range(10):
dict1['name']['routes'][f'route{i}'] = {'bit_value': i}
A few bonus tips
Don't mix 'string' with "string"
Use for i in range(10) instead of a while loop. Much simpler and easier to read
Use f-string to format string f'route{i}'
As a matter of fact, your code can also be achieved with dictionary comprehension
dict1 = {'name': {'domain': 'something'}}
dict1['name']['routes'] = {f'route{i}': {'bit_value': i} for i in range(10)}

Related

How to list all the keys with the same value in a dictionary? [duplicate]

I have question about Dictionaries in Python.
here it is:
I have a dict like dict = { 'abc':'a', 'cdf':'b', 'gh':'a', 'fh':'g', 'hfz':'g' }
Now i want to get all Key-Elements by the same value and save it in a new dict.
The new Dict should be look like:
new_dict = { 'b':('cdf'), 'a':('abc','gh'), 'g':('fh','hfz')}
If you are fine with lists instead of tuples in the new dictionary, you can use
from collections import defaultdict
some_dict = { 'abc':'a', 'cdf':'b', 'gh':'a', 'fh':'g', 'hfz':'g' }
new_dict = defaultdict(list)
for k, v in some_dict.iteritems():
new_dict[v].append(k)
If you want to avoid the use of defaultdict, you could also do
new_dict = {}
for k, v in some_dict.iteritems():
new_dict.setdefault(v, []).append(k)
Here's a naive implementation. Someone with better Python skills can probably make it more concise and awesome.
dict = { 'abc':'a', 'cdf':'b', 'gh':'a', 'fh':'g', 'hfz':'g' }
new_dict = {}
for pair in dict.items():
if pair[1] not in new_dict.keys():
new_dict[pair[1]] = []
new_dict[pair[1]].append(pair[0])
print new_dict
This produces
{'a': ['abc', 'gh'], 'b': ['cdf'], 'g': ['fh', 'hfz']}
If you do specifically want tuples as the values in your new dictionary, you can still use defaultdict, and use tuple concatenation. This solution works in Python 3.4+:
from collections import defaultdict
source = {'abc': 'a', 'cdf': 'b', 'gh': 'a', 'fh': 'g', 'hfz': 'g'}
target = defaultdict(tuple)
for key in source:
target[source[key]] += (key, )
print(target)
Which will produce
defaultdict(<class 'tuple'>, {'a': ('abc', 'gh'), 'g': ('fh', 'hfz'), 'b': ('cdf',)})
This will probably be slower than generating a dictionary by list insertion, and will create more objects to be collected. So, you can build your dictionary out of lists, and then map it into tuples:
target2 = defaultdict(list)
for key in source:
target2[source[key]].append(key)
for key in target2:
target2[key] = tuple(target2[key])
print(target2)
Which will give the same result as above.
It can be done this way too, without using any extra functions .
some_dict = { 'abc':'a', 'cdf':'b', 'gh':'a', 'fh':'g', 'hfz':'g' }
new_dict = { }
for keys in some_dict:
new_dict[some_dict[keys]] = [ ]
for keys in some_dict:
new_dict[some_dict[keys]].append(keys)
print(new_dict)

How to iterate through a list of dictionaries

My code is
index = 0
for key in dataList[index]:
print(dataList[index][key])
Seems to work fine for printing the values of dictionary keys for index = 0. However, I can't figure out how to iterate through an unknown number of dictionaries in dataList.
You could just iterate over the indices of the range of the len of your list:
dataList = [{'a': 1}, {'b': 3}, {'c': 5}]
for index in range(len(dataList)):
for key in dataList[index]:
print(dataList[index][key])
or you could use a while loop with an index counter:
dataList = [{'a': 1}, {'b': 3}, {'c': 5}]
index = 0
while index < len(dataList):
for key in dataList[index]:
print(dataList[index][key])
index += 1
you could even just iterate over the elements in the list directly:
dataList = [{'a': 1}, {'b': 3}, {'c': 5}]
for dic in dataList:
for key in dic:
print(dic[key])
It could be even without any lookups by just iterating over the values of the dictionaries:
dataList = [{'a': 1}, {'b': 3}, {'c': 5}]
for dic in dataList:
for val in dic.values():
print(val)
Or wrap the iterations inside a list-comprehension or a generator and unpack them later:
dataList = [{'a': 1}, {'b': 3}, {'c': 5}]
print(*[val for dic in dataList for val in dic.values()], sep='\n')
the possibilities are endless. It's a matter of choice what you prefer.
You can easily do this:
for dict_item in dataList:
for key in dict_item:
print(dict_item[key])
It will iterate over the list, and for each dictionary in the list, it will iterate over the keys and print its values.
use=[{'id': 29207858, 'isbn': '1632168146', 'isbn13': '9781632168146', 'ratings_count': 0}]
for dic in use:
for val,cal in dic.items():
print(f'{val} is {cal}')
def extract_fullnames_as_string(list_of_dictionaries):
return list(map(lambda e : "{} {}".format(e['first'],e['last']),list_of_dictionaries))
names = [{'first': 'Zhibekchach', 'last': 'Myrzaeva'}, {'first': 'Gulbara', 'last': 'Zholdoshova'}]
print(extract_fullnames_as_string(names))
#Well...the shortest way (1 line only) in Python to extract data from the list of dictionaries is using lambda form and map together.
"""The approach that offers the most flexibility and just seems more dynamically appropriate to me is as follows:"""
Loop thru list in a Function called.....
def extract_fullnames_as_string(list_of_dictionaries):
result = ([val for dic in list_of_dictionaries for val in
dic.values()])
return ('My Dictionary List is ='result)
dataList = [{'first': 3, 'last': 4}, {'first': 5, 'last': 7},{'first':
15, 'last': 9},{'first': 51, 'last': 71},{'first': 53, 'last': 79}]
print(extract_fullnames_as_string(dataList))
"""This way, the Datalist can be any format of a Dictionary you throw at it, otherwise you can end up dealing with format issues, I found. Try the following and it will still works......."""
dataList1 = [{'a': 1}, {'b': 3}, {'c': 5}]
dataList2 = [{'first': 'Zhibekchach', 'last': 'Myrzaeva'}, {'first':
'Gulbara', 'last': 'Zholdoshova'}]
print(extract_fullnames_as_string(dataList1))
print(extract_fullnames_as_string(dataList2))
Another pythonic solution is using collections module.
Here is an example where I want to generate a dict containing only 'Name' and 'Last Name' values:
from collections import defaultdict
test_dict = [{'Name': 'Maria', 'Last Name': 'Bezerra', 'Age': 31},
{'Name': 'Ana', 'Last Name': 'Mota', 'Age': 31},
{'Name': 'Gabi', 'Last Name': 'Santana', 'Age': 31}]
collect = defaultdict(dict)
# at this moment, 'key' becomes every dict of your list of dict
for key in test_dict:
collect[key['Name']] = key['Last Name']
print(dict(collect))
Output should be:
{'Name': 'Maria', 'Last Name': 'Bezerra'}, {'Name': 'Ana', 'Last Name': 'Mota'}, {'Name': 'Gabi', 'Last Name': 'Santana'}
There are multiple ways to iterate through a list of dictionaries. However, if you are into Pythonic code, consider the following ways, but first, let's use data_list instead of dataList because in Python snake_case is preferred over camelCase.
Way #1: Iterating over a dictionary's keys
# let's assume that data_list is the following dictionary
data_list = [{'Alice': 10}, {'Bob': 7}, {'Charlie': 5}]
for element in data_list:
for key in element:
print(key, element[key])
Output
Alice 10
Bob 7
Charlie 5
Explanation:
for element in data_list: -> element will be a dictionary in data_list at each iteration, i.e., {'Alice': 10} in the first iteration,
{'Bob': 7} in the second iteration, and {'Charlie': 5}, in the third iteration.
for key in element: -> key will be a key of element at each iteration, so when element is {'Alice': 10}, the values for key will be 'Alice'. Keep in mind that element could contain more keys, but in this particular example it has just one.
print(key, element[key]) -> it prints key and the value of element for key key, i.e., it access the value of key in `element.
Way #2: Iterating over a dictionary's keys and values
# let's assume that data_list is the following dictionary
data_list = [{'Alice': 10}, {'Bob': 7}, {'Charlie': 5}]
for element in data_list:
for key, value in element.items():
print(key, value)
The output for this code snippet is the same as the previous one.
Explanation:
for element in data_list: -> it has the same explanation as the one in the code before.
for key, value in element.items(): -> at each iteration, element.items() will return a tuple that contains two elements. The former element is the key, and the latter is the value associated with that key, so when element is {'Alice': 10}, the value for key will be 'Alice', and the value for value will be 10. Keep in mind that this dictionary has only one key-value pair.
print(key, value) -> it prints key and value.
As stated before, there are multiple ways to iterate through a list of dictionaries, but to keep your code more Pythonic, avoid using indices or while loops.
had a similar issue, fixed mine by using a single for loop to iterate over the list, see code snippet
de = {"file_name":"jon","creation_date":"12/05/2022","location":"phc","device":"s3","day":"1","time":"44692.5708703703","year":"1900","amount":"3000","entity":"male"}
se = {"file_name":"bone","creation_date":"13/05/2022","location":"gar","device":"iphone","day":"2","time":"44693.5708703703","year":"2022","amount":"3000","entity":"female"}
re = {"file_name":"cel","creation_date":"12/05/2022","location":"ben car","device":"galaxy","day":"1","time":"44695.5708703703","year":"2022","amount":"3000","entity":"male"}
te = {"file_name":"teiei","creation_date":"13/05/2022","location":"alcon","device":"BB","day":"2","time":"44697.5708703703","year":"2022","amount":"3000","entity":"female"}
ye = {"file_name":"js","creation_date":"12/05/2022","location":"woji","device":"Nokia","day":"1","time":"44699.5708703703","year":"2022","amount":"3000","entity":"male"}
ue = {"file_name":"jsdjd","creation_date":"13/05/2022","location":"town","device":"M4","day":"5","time":"44700.5708703703","year":"2022","amount":"3000","entity":"female"}
d_list = [de,se,re,te,ye,ue]
for dic in d_list:
print (dic['file_name'],dic['creation_date'])

Python Dict Comprehension to Create and Update Dictionary

I have a list of dictionaries (data) and want to convert it into dictionary (x) as below.
I am using following ‘for loop’ to achieve.
data = [{'Dept': '0123', 'Name': 'Tom'},
{'Dept': '0123', 'Name': 'Cheryl'},
{'Dept': '0123', 'Name': 'Raj'},
{'Dept': '0999', 'Name': 'Tina'}]
x = {}
for i in data:
if i['Dept'] in x:
x[i['Dept']].append(i['Name'])
else:
x[i['Dept']] = [i['Name']]
Output:
x -> {'0999': ['Tina'], '0123': ['Tom', 'Cheryl', 'Raj']}
Is it possible to implement the above logic in dict comprehension or any other more pythonic way?
The dict comprehension, even though not impossible, might not be the best choice. May I suggest using a defaultdict:
from collections import defaultdict
dic = defaultdict(list)
for i in data:
dic[i['Dept']].append(i['Name'])
It seems way too complicated to be allowed into any code that matters even the least bit, but just for fun, here you go:
{
dept: [item['Name'] for item in data if item['Dept'] == dept]
for dept in {item['Dept'] for item in data}
}

Adding a key value pair to a list of dicts based on another list Python

Sorry if the title is not clear, but here is what I'm trying to achieve.
I have a list of dicts :
l = [{'name': 'inAnalysis'}, {'name': 'inQuest'}, {'name': 'inDevelopment'}]
And a sort of translation table like this :
tr = {'inAnalysis' : 1, 'inDevelopment' : 2, 'inQuest' : 3}
I want to add the key value to l like this :
l = [{'name': 'inAnalysis', 'order' : 1},
{'name': 'inQuest', 'order' : 3},
{'name': 'inDevelopment', 'order' : 2}]
How can I match the value of l with the key of tr and get its value with the key order and add it to l? Any help would be appreciated. I'm using Python 2.6.
You can use list comprehension to dynamically generate the dictionaries like this
print [{"name":dic["name"], "order":tr[dic["name"]]} for dic in l]
Output
[{'name': 'inAnalysis', 'order': 1},
{'name': 'inQuest', 'order': 3},
{'name': 'inDevelopment', 'order': 2}]
Alternatively, you can use the following
for dic in l: dic["order"] = tr[dic["name"]]
this modifies the dictionaries in-place.
If you want to modify the existing dictionaries in place (note that thefoutheye's solution makes new dictionaries which could concievably be a problem if something else in your code is holding a reference to the dictionaries in the list, rather than the list itself) you can do:
for my_dict in l:
my_dict['order'] = tr[my_dict['name']]

Dictionary transformation and counter

Object:
data = [{'key': 11, 'country': 'USA'},{'key': 21, 'country': 'Canada'},{'key': 12, 'country': 'USA'}]
the result should be:
{'USA': {0: {'key':11}, 1: {'key': 12}}, 'Canada': {0: {'key':21}}}
I started experiment with:
result = {}
for i in data:
k = 0
result[i['country']] = dict(k = dict(key=i['key']))
and I get:
{'Canada': {'k': {'key': 21}}, 'USA': {'k': {'key': 12}}}
So how can I put the counter instead k? Maybe there is a more elegant way to create the dictionary?
I used the len() of the existing result item:
>>> import collections
>>> data = [{'key': 11, 'country': 'USA'},{'key': 21, 'country': 'Canada'},{'key': 12, 'country': 'USA'}]
>>> result = collections.defaultdict(dict)
>>> for item in data:
... country = item['country']
... result[country][len(result[country])] = {'key': item['key']}
...
>>> dict(result)
{'Canada': {0: {'key': 21}}, 'USA': {0: {'key': 11}, 1: {'key': 12}}}
There may be a more efficient way to do this, but I thought this would be most readable.
#zigg's answer is better.
Here's an alternative way:
import itertools as it, operator as op
def dict_transform(dataset, key_name=None, group_by=None):
result = {}
sorted_dataset = sorted(data, key=op.itemgetter(group_by))
for k,g in it.groupby(sorted_dataset, key=op.itemgetter(group_by)):
result[k] = {i:{key_name:j[key_name]} for i,j in enumerate(g)}
return result
if __name__ == '__main__':
data = [{'key': 11, 'country': 'USA'},
{'key': 21, 'country': 'Canada'},
{'key': 12, 'country': 'USA'}]
expected_result = {'USA': {0: {'key':11}, 1: {'key': 12}},
'Canada': {0: {'key':21}}}
result = dict_transform(data, key_name='key', group_by='country')
assert result == expected_result
To add the number, use the {key:value} syntax
result = {}
for i in data:
k = 0
result[i['country']] = dict({k : dict(key=i['key'])})
dict(k = dict(key=i['key']))
This passes i['key'] as the key keyword argument to the dict constructor (which is what you want - since that results in the string "key" being used as a key), and then passes the result of that as the k keyword argument to the dict constructor (which is not what you want) - that's how parameter passing works in Python. The fact that you have a local variable named k is irrelevant.
To make a dict where the value of k is used as a key, the simplest way is to use the literal syntax for dictionaries: {1:2, 3:4} is a dict where the key 1 is associated with the value 2, and the key 3 is associated with the value 4. Notice that here we're using arbitrary expressions for keys and values - not names - so we can use a local variable and the resulting dictionary will use the named value.
Thus, you want {k: {'key': i['key']}}.
Maybe there is a more elegant way to create the dictionary?
You could create a list by appending items, and then transform the list into a dictionary with dict(enumerate(the_list)). That at least saves you from having to do the counting manually, but it's pretty indirect.

Categories