I have a dictionary which looks like this:
store = {}
And I have a bunch of data in another dictionary that looks like this:
items = {"hardware_items":23, "fruit_items":5, "fish_items": 23}
How can I put the items dictionary inside the store dict so I can achieve the following result?
store = {"hardware_items":23, "fruit_items":5, "fish_items": 23}
Thank you
Use the update method:
store.update(items)
This will add everything in items to store; beware though that if store already has existing keys with those names they will be overwritten.
If store dict is empty you can use the copy() method :
store = items.copy()
You can use store = items but it works as a reference (then modifying store will modify items)
Else, you can use a for loop :
for keys in items:
store[keys] = items[keys]
It will overwrite value if a key is already declared.
The output you want would appear to be a copy of the "items" dictionary in "store". You can do this, basically, in two ways.
1. Simple copy
You can write
store = items
and the output will be what you asked for.
Changing one of the two dictionaries, however, will also change the other.
2. Deep Copy
One of the ways to do a deep copy is:
store=copy.deepcopy(items)
In this case you will have two dictionaries with the same content, but they will be independent and you can edit them separately. Let me show an example:
import copy
store = {}
items = {"hardware_items":23, "fruit_items":5, "fish_items": 23}
#Print
print("Before operations")
print("ITEMS> "+str(items))
print("STORE> "+str(store))
store=copy.deepcopy(items)
#Print
print("After deep copy")
print("ITEMS> "+str(items))
print("STORE> "+str(store))
items["hardware_items"]=3
#Print
print("let's modify the first key value")
print("ITEMS> "+str(items))
print("STORE> "+str(store))
Your output will be:
Related
Code:
std::map<CString, S_DISCUSSION_HIST_ITEM> mapHistory;
// History list is in ascending date order
for (auto& sHistItem : m_listDiscussionItemHist)
{
if (m_bFullHistoryMode)
mapHistory.emplace(sHistItem.strName, sHistItem);
else if (sHistItem.eSchool == m_eActiveSchool)
mapHistory.emplace(sHistItem.strName, sHistItem);
}
// The map is sorted by Name (so reset by date later)
// The map has the latest assignment info for each Name now
Observation:
I now understand that std::emplace behaves like this:
The insertion only takes place if no other element in the container has a key equivalent to the one being emplaced (keys in a map container are unique).
Therefore my code is flawed. What I was hoping to acheive (in pseudo code) is:
For Each History Item
Is the name in the map?
No, so add to map with sHitItem
Yes, so replace the sHistItem with this one
End Loop
By the end of this loop iteration I want to have the most recent sHitItem, for each person. But as it is, it is only adding an entry into the map if the name does not exist.
What is the simplest way to get around this?
Use insert_or_assign method if the item is assignable. It will be assigned if it already exists. Or use [] operator followed by assignment, it will default-construct item if it does not exist.
For non-assignable types I'm afraid there's no convenient way.
This question already has an answer here:
How can I replace a key:value pair by its value wherever the chosen key occurs in a deeply nested dictionary?
(1 answer)
Closed 1 year ago.
About
This question is about the most basic problem of deleting a key:value pair at a found key, iterating over a whole dictionary.
Other questions
Deleting a key:value pair should happen much more often than the special problem of replacing the key:value pair by its value at How can I replace a key:value pair by its value whereever the chosen key occurs in a deeply nested dictionary?. Saying that these two problems are different enough may not sound so plausible at first since the wording seems almost the same, but then, please check the code solutions and test it. There is a reason why it took some hour to find it out.
The 2011 question Modifying a Python dict while iterating over it (85k views) does not even seem to have found a working answer, though it is also outdated, admittedly.
Before:
I have a dictionary that is nested many times.
{
"key0": {
"key1a": {
"sub_key2a": "sub_value2a",
"sub_key2b": "sub_value2b"
},
"key1b": {
"key_XYZ": {
"sub_key2a": "sub_value2a",
"sub_key2b": "sub_value2b"
}
}
}
}
After:
The result should look like this, deleting all "sub_key2a" keys with their values:
{
"key0": {
"key1a": {
"sub_key2b": "sub_value2b"
},
"key1b": {
"key_XYZ": {
"sub_key2b": "sub_value2b"
}
}
}
}
Modifying a Python dict while iterating over it
When I looped through the items of the dictionary to delete, I got the error
RuntimeError: dictionary changed size during iteration
which needs somehow to be avoided.
How can I remove the "sub_key2a": SOME_VALUE key-value pair each time the key "sub_key2a" occurs somewhere in the dictionary?
Trick
The trick is to find out in advance whether a target_key is among the next children (= this_dict[key] = the values of the current dict iteration) before you reach the child level recursively. Only then you can still delete a key:value pair of the child level while iterating over a dictionary. Once you have reached the same level as the key to be deleted and then try to delete it from there, you get the error:
RuntimeError: dictionary changed size during iteration
Code
Thus, the code looks as follows:
import copy
def find_remove(this_dict, target_key, bln_overwrite_dict=False):
if not bln_overwrite_dict:
this_dict = copy.deepcopy(this_dict)
for key in this_dict:
# if the current value is a dict, dive into it
if isinstance(this_dict[key], dict):
if target_key in this_dict[key]:
this_dict[key].pop(target_key)
this_dict[key] = find_remove(this_dict[key], target_key)
return this_dict
dict_nested_new = find_remove(nested_dict, "sub_key2a")
Credits
This is almost a copy of the spin-off How can I replace a key:value pair by its value wherever the chosen key occurs in a deeply nested dictionary?. But it took me a while to change that answer so that it would delete a key:value by its key. That is why I am sharing this, please mind that 95% of the credits go to the link!
The main added value over the "spun-off answer" is that you search for the target_key in the values in advance of entering the next recursion level by checking if target_key in this_dict[key]:.
Side note: Formatting the output
If you want to print or save the dictionary nicely, see How do I write JSON data to a file?.
delete a["key_"]["key0a"]["sub_key2a"]
driver_data_form = {
'forc_day_off':[],
'pref_day_off':[],
'pref_shift':{"day"+str(i):None for i in range(1,15)},
'route_data':[]
}
So I am creating the dict driver_data (seen below) by using driver_data_form (seen above)
driver_data = {str(i):driver_data_form for i in range(1,12)}
and accordingly populating it :
loop_list = [str(i) for i in range(1,13)]
1 for specific_driver in loop_list:
2 for driver in forced_day_off_data:
3 for day in driver:
4 if driver[day]=='1' and day != "driverid":
5 driver_data[specific_driver]['forc_day_off'].append(day)
forced_day_off_data looks like:
But for some reason, after the above loop is executed once (lines 2-5), and by placing a break point in line 2, I am getting all 11 values of my driver_data[forc_day_off] dictionary populated, instead of only the first one. It appears that the values of the first key are copied to all the rest of the values:
I debugged this piece of code many times and this behavior makes no sence to me? What could be causing this and how can I fix it?
The problem with your code is that python is using references to dicts and lists. When you do this
driver_data = {str(i):driver_data_form for i in range(1,12)}
It basically sets the same dict reference for all your keys so when you change one value you actually update for all the other keys since it's the same dict
For your code to work you need to do this:
driver_data = {str(i):{
'forc_day_off':[],
'pref_day_off':[],
'pref_shift':{"day"+str(j):None for j in range(1,15)},
'route_data':[]
} for i in range(1,12)}
This way you create a new dict for each element and you will update only the specific dict.
See this this link to better understand the difference.
I am iterating over a collection of data, in my case, an array of objects. Here is a sample of 2 data points from it:
{
violation_id: '211315',
inspection_id: '268804',
violation_category: 'Garbage and Refuse',
violation_date: '2012-03-22 0:00',
violation_date_closed: '',
violation_type: 'Refuse Accumulation' },
{
violation_id: '214351',
inspection_id: '273183',
violation_category: 'Building Conditions',
violation_date: '2012-05-01 0:00',
violation_date_closed: '2012-04-17 0:00',
violation_type: 'Mold or Mildew' }
I need to create a new array of objects from this, one for each "violation_category" property. If Violation category already exists in the new array I am creating, i simply add the information to that existing category object (instead of having two "building conditions" objects for example, I would just add to an existing one).
However, I am having trouble assigning to the existing object if the current one exists (it's easy to check if it does not, but not the other way around). This is what am attempting to do currently:
if (violationCategory.uniqueCategoryName) {
violationCategory.uniqueCategoryName.violations = results[i].violation_id;
violationCategory.uniqueCategoryName.date = results[i].violation_date;
violationCategory.uniqueCategoryName.closed =
results[i].violation_date_closed;
} else {
category.violations = results[i].violation_id;
category.date = results[i].violation_date;
category.closed = results[i].violation_date_closed;
violationCategory.push(category);
}
In first condition, if this category (key) exists, I simply add to it, and in the second condition, this is where I am struggling. Any help appreciated. Thanks guys.
Just add an empty object to the key if there no object there :
violationCategory.uniqueCategoryName = violationCategory.uniqueCategoryName || {};
And only then, add the data you want to the object.
violationCategory.uniqueCategoryName.violations = results[i].violation_id;
violationCategory.uniqueCategoryName.date = results[i].violation_date;
violationCategory.uniqueCategoryName.closed =
results[i].violation_date_closed;
No condition needed.
Good luck!
Assuming that you have an input variable which is an array of objects, where the objects are looking like the objects of the question, you can generate your output like this:
var output = {};
for (var item of input) {
if (!output[item.violation_category]) output[item.violation_category] = [];
output[item.violation_category].push(item);
}
Of course you might customize it like you want.
I have a program that prompts the user for three pieces of input:
Student No.
Name
Age
I then populate a list with this info. This currently works fine.
I was wanting to change the list construct to a dictionary that has the Student No. as the key and a list with the Name and Age as values. I also want the list in case I decide to enlarge the number of inputs in the future.
I was wondering if I could use a dict comprehension but I can't find any examples of using a dict comp being used to create a dict with a list as the value.
The resulting dictionary would look like:
st_dict = {101: [Mark, 54],
102: [Bob, 49]
}
Is it possible, using a dict comp, to create this structure?
Basically I am wanting to do this:
st_dict = {Student_no: [Name, Age] per student entered}