Difficulty understanding changes to dictionary - python

I was looking through old posts in order to find a method of changing values in a dictionary by iterating through the items.
dictionary = {
1: [
{
"id": "1234",
"cow": "parts/sizes/lakes"
},
{
"id": "5151",
"cow": "minors/parts"
}
]}
def fetchanswers():
for item in dictionary[1]:
yield(item["id"], item["cow"])
for a, b in fetchanswers():
k = {}
k["id"] = a
k["cow"] = b.replace("parts", a)
My understanding is that yield returns the two items from either object in the dictionary and the for loop creates a new dictionary and appends the values obtained from fetchanswers() and parts is replaced by id.
I don't understand how k["id"] can be referred to when the dictionary is empty.

a method of changing values in a dictionary
Your values are strings. Strings are immutable, so you need to overwrite the dictionary using existing keys
You don't need another dictionary for this
# replace "parts" text value with the value of the id key
for item in list_of_dicts:
item["cow"] = item["cow"].replace("parts", str(item["id"]))
how k["id"] can be referred to
It's not a referral when there's an equal sign afterwards. It's an assignment

Related

Adding items in a dictionary but the precious value seems to be overwritten via for loop in Python

I have a list sample_list like this:
[
{
"Meta": {
"ID": "1234567",
"XXX": "XXX"
},
"bbb": {
"color":red"
},
{
"Meta": {
"ID": "78945612",
"XXX": "XXX"
},
"bbb": {
"color":"blue"
}
]
now I want to extract the field "ID" and the values then put them in a dict object, I tried:
init_dict = {}
for item in sample_list:
init_dict['ID'] = item['Meta']['ID']
print(init_dict)
This returns:
{'ID': '1234567'}
{'ID': '78945612'}
Seems like the second value overwrite the first one, if I print from outside of the iteration:
init_dict = {}
for item in sample_list:
init_dict['ID'] = item['Meta']['ID']
print(init_dict)
This only return the last value:
{'ID': '78945612'}
Combining with the comment below, I realise the logic here is wrong, since the key name is always 'ID', I'VE updated the example in the question, can we take the value for ID as the new key and taking the value for color as the new value?
Expected output is something like
{'1234567':'red', '78945612':'blue'}
can someone help please? Thanks.
The problem is in the second line of a for loop. What you are doing is that you are creating a dictionary in this forloop. In any other language, you would get a syntax error, because you are trying to access un-initialised variable (in this case init_dict) (in this case, if sample_list is empty, you will get an error that init_dict does not exist)
for item in sample_list:
init_dict = {} // here
init_dict['ID'] = item['Meta']['ID']
print(init_dict)
Simple fix is to move it outside of a for loop
init_dict = {}
for item in sample_list:
init_dict['ID'] = item['Meta']['ID']
print(init_dict)
color edit:
init_dict = {}
for item in sample_list:
init_dict[item['Meta']['ID']] = item['bbb']['color']
print(init_dict)
Here you can see that you can use anything as a key, but be careful, the key has to unique, so in this case, ID is a very good key, but if there is a chance that you can get a duplicate ID, I recommend you to find a better key. Also, if you do not need the dictionary in first place, I recommend using just a list of tuples (i.e -> [(key, val), (key2, val2), (key3, val3)]. The list has no problem with duplicities
Every time you are looping, you are just overwriting the same dictionary. Now, it prints both the elements in the first method because your print statement is inside the for loop. In the second method, your print statement is outside the for loop. So, it prints only the last value that you gave which is 78945612.
Here you are just overwriting the same dictionary. So, every time you change the ID, it just stores the last value that you gave.
You need to append to your dictionary. The line init_dict = {} resets your dictionary. Instead you should do:
init_dict = {'ID':[]}
for item in sample_list:
init_dict['ID'].append(item['Meta']['ID'])
print(init_dict)
To satisfy the request you made in a comment, you can do this to use the value as a key and then add a colour:
init_dict = {}
for item in sample_list:
init_dict[item['Meta']['ID']] = "red"

Update dicitonary key with every value from a list

Given this list:
pc = ['OferteConfigurabile_S2D_Rate',
'OferteConfigurabile_S2D_Rate_si_Discount',
'OferteConfigurabile_S2D_SimOnly_si_Discount',
'OferteConfigurabile_S2D_SimOnly',
'OferteConfigurabile_S2D_VMM_Rate']
And this dictionary:
lst = []
dataModel = {
'channel': 'RETAIL',
'searchType': 'MSISDN',
'searchValue': 727277696,
'configType': 'RETENTIE',
'scenarioName_PC': 'OferteConfigurabile_ServiceOnly',
'retention_option': '360_OFERTE_MOBILE',
'retention_flow': 'ConfigureazaOferte',
}
I want for every element in the 'pc' list to update dateModel['scenarioName_PC'] and store the resulting dictionary into a list but slightly changed by creating a new dict with a custom key and dataModel dictionary as its value
for i in pc:
dataModel['scenarioName_PC'] = i
lst.append({f"{dataModel['retention_option']}_{dataModel['retention_flow']}_{i}" : dataModel})
print(lst)
The problem is that when i print the list 'scenarioName_PC' key always has the last element from the iterated list, the dataModel dictionary dosen't save the value for every for loop iteration, it somehow only stores the last value in PC list
[
{
"360_OFERTE_MOBILE_ConfigureazaOferte_OferteConfigurabile_S2D_Rate":{
"channel":"RETAIL",
"searchType":"MSISDN",
"searchValue":727277696,
"configType":"RETENTIE",
"scenarioName_PC":"OferteConfigurabile_S2D_VMM_Rate",
"retention_option":"360_OFERTE_MOBILE",
"retention_flow":"ConfigureazaOferte"
}
},
{
"360_OFERTE_MOBILE_ConfigureazaOferte_OferteConfigurabile_S2D_Rate_si_Discount":{
"channel":"RETAIL",
"searchType":"MSISDN",
"searchValue":727277696,
"configType":"RETENTIE",
"scenarioName_PC":"OferteConfigurabile_S2D_VMM_Rate",
"retention_option":"360_OFERTE_MOBILE",
"retention_flow":"ConfigureazaOferte"
}
},
Expected result is a list with dataModel dictionary but for scenarioname_PC key to have every time 'i' as value.
[
{
"360_OFERTE_MOBILE_ConfigureazaOferte_OferteConfigurabile_S2D_Rate":{
"channel":"RETAIL",
"searchType":"MSISDN",
"searchValue":727277696,
"configType":"RETENTIE",
"scenarioName_PC":"OferteConfigurabile_S2D_Rate",
"retention_option":"360_OFERTE_MOBILE",
"retention_flow":"ConfigureazaOferte"
}
},
{
"360_OFERTE_MOBILE_ConfigureazaOferte_OferteConfigurabile_S2D_Rate_si_Discount":{
"channel":"RETAIL",
"searchType":"MSISDN",
"searchValue":727277696,
"configType":"RETENTIE",
"scenarioName_PC":"OferteConfigurabile_S2D_Rate_si_Discount",
"retention_option":"360_OFERTE_MOBILE",
"retention_flow":"ConfigureazaOferte"
}
},
while appending copy the dictionary object instead of just passing the dictionary. You are passing the dictionary reference which is being modified.
This should work.
import copy
for i in pc:
new_dataMode = copy.deepcopy(dataMode)
new_dataModel['scenarioName_PC'] = i
lst.append({f"{new_dataModel['retention_option']}_{new_dataModel['retention_flow']}_{i}" : new_dataModel})
print(lst)

Remove entire JSON object if it contains a specified phrase (from a list in python)

Have a JSON file output similar to:
{
"object1": {
"json_data": "{json data information}",
"tables_data": "TABLES_DATA"
},
"object2": {
"json_data": {json data information}",
"tables_data": ""
}
}
Essentially, if there is an empty string for tables_data as shown in object2 (eg. "tables_data": ""), I want the entire object to be removed so that the output would look like:
{
"object1": {
"json_data": "{json data information}",
"tables_data": "TABLES_DATA"
}
}
What is the best way to go about doing this? Each of these objects correspond to a separate index in a list that I've appended called summary[].
To achieve this, you could iterate through the JSON dictionary and test the tables_data values, adding the objectX elements to a new dictionary if their tables_data value passes the test:
new_dict = {k: v for k, v in json_dict.items()
if v.get("tables_data", "") != ""}
If your JSON objectX is stored in a list as you say, these could be processed as follows using a list comprehension:
filtered_summary = [object_dict for object_dict in summary
if object_dict.get("tables_data", "") != ""]
Unless you have compelling reasons to do otherwise, the pythonic way to filter out a list or dict (or any iterable) is not to change it in place but to create a new filtered one. For your case this would look like
raw_data = YOUR_DICT_HERE_WHEREVER_IT_COMES_FROM
# NB : empty string have a false value in a boolean test
cleaned_data = {k:v for k, v in raw_data.items() if not v["table_data"]}

How to properly create a dictionary in Python

I am trying to create a dictionary in a function but I don't know for which reason I got this:
MONdic = {"mama"}
print MONdic
What I get as a result is :
set(['mama'])
Any help ?
dict is based on key value pairs (You have created a set)
d = {'key':'val'}
By default, if you pass an element or list of elements to {}, it will create a set.
But if you try passing key value pairs to {}, it will create a dictionary.
MONdic = {"key":"value"}, then the value of MONdic will be {"key":"value"}
dictionary must has keys and values
like:
my_dict = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}
check https://www.w3schools.com/python/python_dictionaries.asp
for accessing it, changing values, loop it ..
But the problem is that I have a second dictionary that should merge with MONdic as in this example:
for key, value in results.items():
MONdic[key].extend(value)
To be able to merge these two dictionaries, they need to have the same keys. The values of MONdic should be empty in the beginning and I don't want to receive these kind of results if I do so :
MONdic = {"mama":[]}
for key, value in results.items():
MONdic[key].extend(value)
>>>> {"mama":[[1,2,5,9]]}

Appending something to a list within a dict within a list in Python

I am attempting to create a list of dicts which will have the following structure:
[
{
'id': '234nj233nkj2k4n52',
'embedded_list': []
},
{
'id': 'jb234bhj23423h4b4',
'embedded_list': []
},
...
]
Initially, this list will be empty.
What I need to be able to do is:
Check to see if a dict with a specific id exists in the list already
If a dict containing that id exists, append something to it's embedded_list
If a dict containing that id does not exist, create a dict, append it to the list.
I am aware of being able to test if a dict exists in a list based on something inside that dict using something like this:
extracted_dict = next((item for item in list if item['id'] == unique_id), None)
I am unsure of how to append something to a list within a dict within a list efficiently. Is there an obvious way which I'm not seeing (probably)?
Thank you in advance.
Your data structure should be a dictionary of dictionaries in the first place:
{'234nj233nkj2k4n52': {'embedded_list': []},
'jb234bhj23423h4b4': {'embedded_list': []},
... }
This will make all your desired operations much easier. If the inner dictionaries only contain the embedded list, this can be further simplified to
{'234nj233nkj2k4n52': [],
'jb234bhj23423h4b4': [],
... }
Now, all you need is a collections.defaultdict(list):
from collections import defaultdict
d = defaultdict(list)
d['234nj233nkj2k4n52'].append(whatever)
or just a simple dic
{
'234nj233nkj2k4n52' : [],
'jb234bhj23423h4b4' : []
}

Categories