How to insert an element into a nested dictionary - python-3.x

I have a dictionary that I want to use to describe data that changes with time. I want to then create an outer dictionary that has time increments as the keys and the previously mentioned dictionary as the value.
However, when I try to change one element in the nested dictionary in a given time step all of the time steps with the same dictionary key are changed as well.
I would like to have the same keys for the inner dictionaries but be able to insert unique values for the different time steps.
Any ideas why this is occurring?
time = 3
inner_dict = dict([(i,[]) for i in ['a','b','c']])
outer_dict= dict([(time_step,inner_dict) for time_step in range(time)])
test[1]['a'] = 20
print(test[2]['a'])
test[2]['a'] should still be an empty list. Or at least that's what I want to achieve.

This is happening because you are passing reference to the same mutable inner_dict to each time step in the outer dictionary. You need to create a separate instance of inner dict for each time step. Try doing something like this:
outer = dict([(time_step, {i:[] for i in ['a', 'b', 'c']}) for time_step in range(time)])
Or simply in dict comprehension
outer = {timestep: {i:[] for i in ['a', 'b', 'c']} for timestep in range(time)}

Related

Assign values from list to specific values in a list of dictionaries

I have list of values:
list = [value1, value2, value3]
And a list of dictionaries where on specific keys I must set the corresponding values:
dictionaries = [{"key1":{"key2":{"key3":position_value1}}},{"key1":{"key2":{"key3":position_value2}}}]
I'm trying to assign the values avoiding solutions that requires do explicit iteration over the numerical indexes of list and dictionaries.
I find the next pseudo-solution iterating over two iterables at the same time using for-each loops
for (dict, value) in zip(dictionaries, list):
dict['key1']['key2']['key3'] = value
print(dictionaries)
But doesn't work due to, all dictionaries take only the last value of the list of values, obtaining the next result:
[{"key1":{"key2":{"key3":position_value3}}},{"key1":{"key2":{"key3":position_value3}}}]
It's important to note that when creating the list of dictionaries the dict.copy() method was used, but maybe this doesn't take affect in the reference allocated in nested dictionaries.
Dictionary list creation
base_dict = {"key1": {"key2":{"key3": None}}}
dictionaries = [base_dict.copy() for n in range(3)]
I appreciate any compact solution, even solutions based on unpacking.
base_dict = {"key1": {"key2":{"key3": None}}}
dictionaries = [base_dict.copy() for n in range(3)]
Will create shallow copies of base_dict. That means that while these are indepenedent at the top level, their values are copied by reference; hence, the inner dictionaries {"key2":{"key3": None}} are still all the same object. When rebinding key3, all references will be affected.
You can avoid that by making a deepcopy:
from copy import deepcopy
dictionaries = [deepcopy(base_dict) for _ in range(3)]

Adding the results of a for loop to the same key in a nested dictionary

I have a dictionary where it includes few sub-dictionaries in it. Each sub-dictionary has many keys. After running a for loop with an if condition too, the results are generated. I want to add ALL the results to under the desired key; but all what my code actually does is adding the result of the last iteration of the loop thereby replacing the value of the previous iteration.
But, actually, i want to print all the results.
for item in list1: #item is a tuple & list1 has tuples in it
if item == node_pair: #node pair is another tuple
high_p[i]["links"] = link_name #"links" is the key
desired output:
"links": [link_name1, link_name2, link_name3]
what i get:
"links" : link_name3
Please guide me..
So each sub-dictionary needs to have lists as values. You could pre-populate each sub-dictionary with lists ahead of time, but it's easier to create them on demand using setdefault.
for item in list1:
if item == node_pair:
high_p[i].setdefault("links", []).append(link_name)

comprehensive dict with multiple or repeated values in python3

I have an extensive list with tuples of pairs. It goes like this:
travels =[(passenger_1, destination_1), (passenger_2, destination_2),(passenger_1, destination_2)...]
And so on. Passengers and destinations may repeat and even the same passenger-destination tuple may repeat.
I want to make a comprehensive dict thay have as key each passenger and as value its most recurrent destination.
My first try was this:
dictionary = {k:v for k,v in travels}
but each key overwrites the last. I was hoping to get multiple values for each key so then i could count for each key. Then I tried like this:
dictionary = {k:v for k,v in travels if k not in dictionary else dictionary[k].append(v)}
but i can't call dictionary inside its own definition. Any ideas on how can i get it done? It's important that it's done comprehensively and not by loops.
That is how it can be done with for loop:
result = dict()
for passenger, destination in travels:
result.setdefault(passenger, list()).append(destination)
result is a single dictionary where keys are passengers, values are lists with destinations.
I doubt you can do the same with a single dictionary comprehesion expression since inside comprehension you can just generate elements but can not freely modify them.
EDIT.
If you want to (or have to) use comprehension expression no matter what then you can do it like this (2 comprehensions and no explicit loops):
result = {
passenger: [destination_
for passenger_, destination_
in travels
if passenger_ == passenger]
for passenger, dummy_destination
in travels}
This is a poor algorithm to get what you want. Its efficiency is O(n^2) while efficiency of the first method is O(n).

Appending values to dictionary/list

I have a mylist = [[a,b,c,d],...[]] with 650 lists inside. I am trying to insert this into a relational database with dictionaries. I have the following code:
for i in mylist:
if len(i) == 4:
cve_ent = {'state':[], 'muni':[], 'area':[]}
cve_ent['state'].append(i[1])
cve_ent['muni'].append(i[2])
cve_ent['area'].append(i[3])
However this code just yields the last list in mylist in the dictionary. I have tried also with a counter and a while loop but I cannot make it run.
I do not know if this is the fastest way to store the data, what I will do is compare the values of the first and second keys with other tables to multiply the values of the third key.
First of all, pull
cve_ent = {'state':[], 'muni':[], 'area':[]}
out of your for loop. That will solve issues with re-writing things.

I want the output to be like {'Red':1,'Blue':2,'Green':3} .I'm only getting {'Green':3}

list_color=['Red','Blue','Green']
for i ,b in enumerate(list_color,1):
if i<=2:
dict ={b:i}
else:
break
i+=1
print(dict)
Output:
{'Green':3}
You told interpreter to reassign name dict with new value, not to update a dict.
dict = {b:i} # we talk about this line
For creating objects based on another iterable, comprehensions are typical way to go, in this case a dictionary comprehension:
colors = ['Red','Blue','Green']
d = {color: idx for idx, color in enumerate(colors, 1)}
# {'Blue': 2, 'Green': 3, 'Red': 1}
Order is not kept, because dictionaries are unordered data structure.
Also, try to avoid naming your objects based on builtins, when dict name is used, it shadows dict builtin function.
I'm not sure why you have so many statements in the for loop, so I'm giving a simple example:
list_color=['Red','Blue','Green']
dict={}
for i ,b in enumerate(list_color,1):
dict[b] = i
print(dict)
Please note, how I define dict to be an empty dictionary before the loop. The other thing I changed is the way you assign values to the dictionary. You were overwriting the complete content of the dictionary with each assignment. I'm showing now how to add values to the dictionary.
I recommend a site like http://www.pythontutor.com/visualize.html which allows to to visualize the execution of the code. Then you can see what's going on/wrong/not according to your expectations.

Resources