list of dict from existing list of dict in python - python

I am very new to Python and wondering some kind of solutions to the below issue.
original_list = [{'Table':'A', 'Column':'C1','Data_Type':'int','Column_Style':None, 'others':'O1'},
{'Table':'A', 'Column':'C2', 'Data_Type':'varchar','Column_Style': '20','others':'O2'},
{'Table':'A', 'Column':'C2', 'Data_Type':'numeric','Column_Style': '10,2','others':'O3'}
]
I want to return a list of dictionary where the key is in ['Table', 'Data_Type', 'Column'] and value of Data_Type is the concatenated value of Data_Type and Column_Style.
# expecting output like below
new_list = [{'Table':'A', 'Column':'C1', 'Data_Type':'int'},
{'Table':'A', 'Column':'C2', 'Data_Type':'varchar(20)'},
{'Table':'A', 'Column':'C2', 'Data_Type':'numeric(10,2)'}
]

new_list = []
for innerDict in original_list:
newDict = {}
for key in innerDict:
if key not in ['Data_Type', 'Column_Style', 'others']:
newDict[key] = innerDict[key]
elif key == 'Data_Type':
if innerDict['Column_Style']:
newDict['Data_Type'] = innerDict['Data_Type'] + '(' + innerDict['Column_Style'] + ')'
else:
newDict['Data_Type'] = innerDict['Data_Type']
new_list.append(newDict)
new_list will contain the output that you requested, assuming that original_list is the input list as you have provided it above.

Actually you can use a generator function to generate a dict that match your criteria for each element in your original list of dict
def gen_dict(ori_dict_list):
columns = ['Table', 'Data_Type', 'Column']
for element in ori_dict_list:
d = {}
for field in columns:
if field == 'Data_Type':
if element['Column_Style'] is None:
d['Data_Type'] = element['Data_Type']
else:
d['Data_Type'] = "{}({})".format(element['Data_Type'], element["Column_Style"])
else:
d[field] = element[field]
yield d
Demo:
>>> from pprint import pprint # Just to pretty print nothing special
>>> pprint(list(gen_dict(original_list)))
[{'Column': 'C1', 'Data_Type': 'int', 'Table': 'A'},
{'Column': 'C2', 'Data_Type': 'varchar(20)', 'Table': 'A'},
{'Column': 'C2', 'Data_Type': 'numeric(10,2)', 'Table': 'A'}]

Related

How to convert list of elements into dictionary of dictionaries

How to turn this list -
list = ['your name', 'mother', 'age', '43']
into this dictionary of dictionaries -
dict = {'your name':
{'mother':
{'age': '43'}
}
}
One option is to iterate backwards over the list, and continuously update the result dict D:
L = ['your name', 'mother', 'age', '43']
D = L[-1] # '43'
for k in L[-2::-1]:
D = {k: D} # {'age': D}... {'mother': D}...
print(D)
Out:
{'your name': {'mother': {'age': '43'}}}
You can just hardcode the logic and then run this in a loop.
l = ['your name', 'mother', 'age', '43']
d = {}
d[l[0]] = {
l[1]: {
l[2]: l[3]
}
}

Remove dictionary if we have value is nan/None/NaN/null for key using python

I want to remove dictionary if value is nan/None/NaN/null for key . If nan is the only value in case of phone_type work then remove full dictionary itself.
Input Data
dic = ['Customer_Number': 12345,'Phone_Number': [{'Phone_Type': 'Mobile', 'Phone': [1217]}, {'Phone_Type': 'work', 'Phone': [nan]}]]
Expected Output Data
dic = ['Customer_Number': 12345,'Phone_Number': [{'Phone_Type': 'Mobile', 'Phone': [1217]}]]
code tried
#define which elements you want to remove:
to_be_deleted = [[], {}, "", None, "nan",nan, "NaN", NaN]
def remove_empty_elements(jsonData):
if isinstance(jsonData, list):
print("jsonDAta:", jsonData)
jsonData = [remove_empty_elements(elem) for elem in jsonData
if remove_empty_elements(elem) not in to_be_deleted]
elif isinstance(jsonData, dict):
jsonData = {key: remove_empty_elements(value) for key, value in jsonData.items()
if remove_empty_elements(value) not in to_be_deleted}
if len(jsonData) == 1:
return None
return jsonData
res = remove_empty_elements(dic)
Example solution:
to_delete = [ None, [None], "", None, "nan", "NaN"]
dic = {'Customer_Number': 12345,'Phone_Number': [{'Phone_Type': 'Mobile', 'Phone': [1217]}, {'Phone_Type': 'work', 'Phone': [None]}]}
for key in dic.keys():
if isinstance(dic[key], list):
for item in dic[key]:
if isinstance(item, dict):
item_keys = list(item.keys())
for key_2 in item_keys:
if item[key_2] in to_delete:
del item[key_2]
output
{'Customer_Number': 12345, 'Phone_Number': [{'Phone_Type': 'Mobile', 'Phone': [1217]}, {'Phone_Type': 'work'}]}
Change accordingly in order to catch more cases. This one only works if you have a list of dictionaries as value for the top level keys

Update a list of Dict based on another Dict

I have a dict as follows.
dict = {'P': ['Demo'], 'Q': ['PMS']}
And I have a list of Dict as follows.
all = [{'Name': 'PMS'}, {'Name': 'Demo'}]
I need to have the dict's respective value in all as bellow.
new_list = [{'Name': 'PMS','Code': 'Q'}, {'Name': 'Demo','Code': 'P'}]
In this specific case, given that the values are just strings and therefore hashable objects, you can use a dictionary of reverse mappings. Be aware that it could not be used if the values were not hashable.
dct = {'P': ['Demo'], 'Q': ['PMS']}
all = [{'Name': 'PMS'}, {'Name': 'Demo'}]
reverse_mapping = {v[0]:k for k, v in dct.items()}
new_list = [d.copy() for d in all]
for d in new_list:
d['Code'] = reverse_mapping[d['Name']]
print(new_list)
This gives:
[{'Name': 'PMS', 'Code': 'Q'}, {'Name': 'Demo', 'Code': 'P'}]
dct = {'P': ['Demo'], 'Q': ['PMS']}
all_ = [{'Name': 'PMS'}, {'Name': 'Demo'}]
out = [dict(**l, Code=next(k for k, v in dct.items() if l['Name'] in v)) for l in all_]
print(out)
Prints:
[{'Name': 'PMS', 'Code': 'Q'}, {'Name': 'Demo', 'Code': 'P'}]
Or: you can make temporary dictionary:
tmp = {v[0]:k for k, v in dct.items()}
out = [dict(**l, Code=tmp[l['Name']]) for l in all_]
print(out)
You could make an inverted dictionary of codes, then go through the list of dictionaries and add the codes in:
codes = {"P": ["Demo"], "Q": ["PMS"]}
lst = [{"Name": "PMS"}, {"Name": "Demo"}]
inverted_codes = {value: key for key, values in codes.items() for value in values}
# {'Demo': 'P', 'PMS': 'Q'}
for dic in lst:
code = dic["Name"]
dic["Code"] = inverted_codes[code]
print(lst)
Output
[{'Name': 'PMS', 'Code': 'Q'}, {'Name': 'Demo', 'Code': 'P'}]

KeyError: 'name' Why can't I use 'name'?

I wanna make a dictionary has name's key & data.In views.py I wrote
data_dict ={}
def try_to_int(arg):
try:
return int(arg)
except:
return arg
def main():
book4 = xlrd.open_workbook('./data/excel1.xlsx')
sheet4 = book4.sheet_by_index(0)
data_dict_origin = OrderedDict()
tag_list = sheet4.row_values(0)[1:]
for row_index in range(1, sheet4.nrows):
row = sheet4.row_values(row_index)[1:]
row = list(map(try_to_int, row))
data_dict_origin[row_index] = dict(zip(tag_list, row))
if data_dict_origin['name'] in data_dict:
data_dict[data_dict_origin['name']].update(data_dict_origin)
else:
data_dict[data_dict_origin['name']] = data_dict_origin
main()
When I printed out data_dict,it is
OrderedDict([(1, {'user_id': '100', 'group': 'A', 'name': 'Tom', 'dormitory': 'C'}), (2, {'user_id': '50', 'group': 'B', 'name': 'Blear', 'dormitory': 'E'})])
My ideal dictionary is
dicts = {
Tom: {
'user_id': '100',
'group': 'A',
'name': 'Tom',
'dormitory': 'C'
},
Blear: {
},
}
How should I fix this?What should I write it?
The code is using the wrong key in the dictionary. The keys are 1, 2, and do not have the name key. You can use this code instead:
for value in data_dict.values():
if value['name'] in data_dict:
data_dict[value['name']].update(value)
else:
data_dict[value['name']] = value
Your data_dict_origin has numbers as keys and dicts as values (which technically makes it a sparse array of dicts). The "name" key exists in those dicts, not in your data_dict.

Filter list of dictionaries

This is my example:
dictlist = [{'first': 'James', 'last': 'Joule'},
{'first': 'James','last': 'Watt'},
{'first': 'Christian','last': 'Doppler'}]
I am trying to get the last name. If this was in a model, the code would be:
getdata = Name.objects.filter(name="Christian")
getLastName = getdata.last
and I would get "Doppler".
This is very simple solution with list comprehension:
>>> dictlist = [{'first': 'James', 'last': 'Joule'}, {'first': 'James','last': 'Watt'},{'first': 'Christian','last': 'Doppler'}]
>>> [x['last'] for x in dictlist if x['first'] == 'Christian']
['Doppler']
dictlist = [{'first': 'James', 'last': 'Joule'}, {'first': 'James','last': 'Watt'},{'first': 'Christian','last': 'Doppler'}]
the_jameses = [d for d in dictlist if d['first'] == 'James']
Where the resulting list contains only:
[{'first': 'James', 'last': 'Joule'}, {'first': 'James', 'last': 'Watt'}]
To start with, we can have a simple script that just uses the built-in python filter method, and this might already be sufficient:
fl = list(filter(lambda x: x['first'] == 'Christian', dictlist))
# you can't use `.property` because this is a dictionary, not a object
fl[0]['last']
# returns Doppler
I realize your example is a Django code, so if you want to make this more dynamic so that you are able to filter by any key in the dictionary:
def dict_filter(dictlist: list, key: str, value: str) -> list:
return list(filter(lambda x: x.get(key) == value, dictlist))
dict_filter(dictlist, 'first', 'Christian')
# similar to django's filter method returns a queryset, this returns a list:
# [{'first': 'Christian', 'last': 'Doppler'}]
dict_filter(dictlist, 'last', 'Doppler')
# returns [{'first': 'Christian', 'last': 'Doppler'}]
dict_filter(dictlist, 'last', 'notfound')
# returns []
And an example to use python filter method to create a similar function to Django's QuerySet.get method:
def dict_get(dictlist: list, key: str, value: str) -> list:
ret = list(filter(lambda x: x.get(key) == value, dictlist))
if len(ret) == 0:
raise Exception('Not Found')
if len(ret) > 1:
raise Exception(f'Found more than 1 object with {key}={value}')
return ret[0]
dict_get(dictlist, 'first', 'Christian')
# returns {'first': 'Christian', 'last': 'Doppler'}
dict_get(dictlist, 'first', 'Christians')
# raises Exception: Not Found
dict_get(dictlist, 'first', 'James')
# raises Exception: Found more than 1 object with first=James
Hope this is helpful to you!
Something like this should work
last_name = ''
for d in dictList:
if d['first'] == 'Christian':
last_name = d['last']
break
I sometimes like to use next:
next((d['last'] for d in dictlist if d['first'] == 'Christian'), None)
# 'Doppler'
The first argument is an iterator and the second (optional) argument is the default value returned if no matching entry is found.
Note: this will only return the first matching result. So it wouldn't be good if you expect to have multiple records matching your "query".
Hope this is helpful to you!!
"; my_dict=[
{
'username':"Siva",
'phoneno':"12345678915",
'city':"Chennai"
},
{
'username':"Sundhar",
'phoneno':"12345678917",
'city':"Vellore"
},
{
'username':"cockroach",
'phoneno':"12345668919",
'city':"Chennai"
},
{
'username':"oggy",
'phoneno':"12345678917",
'city':"Chennai"
}
]
";phoneno="12345678917"
result = [user['username'] for user in my_dict if user['phoneno']== phoneno]
for comp in dictlist:
if comp["first"] == 'Christian':
return comp["last"]

Categories

Resources