Perform algebraic operations with nested dictionaries using "lambda" and "dictionary comprehension"? - python

The problem of multiplying two "simple" dictionaries with the help of lambda, I decided as follows:
v1={'product1': '100', 'product2': '120'}
v2={'product1': '3', 'product2': '2'}
foo = lambda dct_1, dct_2: {key: int(dct_2[key]) * int(dct_1[key]) for key in dct_2}
foo(v1, v2)
# Out: {'product1': 300, 'product2': 240}
How can I multiply two nested dictionaries in the same way?
V={'id1': [{'product1': '1', 'product2': '2'}],'id2': [{'product1': '3', 'product2': '4'}]}
Z={'id1': [{'благо1': '10', 'благо2': '25'}], 'id2': [{'product1': '20', 'product2': '15'}]}
The answer should be as follows:
Out:={'id1': [{'product1': '10', 'product2': '50'}], 'id2': [{'product1': '60', 'product2': '60'}]}
I'm using Python3.

I will omit the lambda because that comprehension is already quite long, but basically you could use:
{outerkey: [{innerkey: int(V[outerkey][0][innerkey])*int(Z[outerkey][0][innerkey])
for innerkey in V[outerkey][0]}]
for outerkey in V}
Giving me:
{'id1': [{'product1': 10, 'product2': 50}],
'id2': [{'product1': 60, 'product2': 60}]}
Note: I assumed that the dictionaries had the same keys:
V={'id1': [{'product1': '1', 'product2': '2'}],'id2': [{'product1': '3', 'product2': '4'}]}
Z={'id1': [{'product1': '10', 'product2': '25'}], 'id2': [{'product1': '20', 'product2': '15'}]}

Related

group dict emelents on lists based on key name

I want to group dict keys in list of dicts based on dict keys name. The dict keys alawys starts with number for example :
{'1_account_id': '5', '1_qty_in': '10.01', '1_uom_in': '1', '2_account_id': '23', '2_qty_in': '2.01', '2_uom_in': '1','3_account_id': '23', '3_qty_in': '2.01', '3_uom_in': '1' ,'some_x':1,'some_y':0}
I want to convert that to list grouped by this number like:
[{'1':{account_id': '5','qty_in':10.01,'uom_in':1}},{'2':{account_id': '23','qty_in':2.01,'uom_in':1}}....] etc
This numbers is not static.
I tried multiple solutions but it seems not good for performace:
Like i looped range for 0 to SOMEBIGNUMBER but this is not a good solution.
i also tried to loop throw the elements to extract the numbers first and then loop again to group but the dict myaybe come not clean as it has other not needed keys.
What should i do ?
So given the input d
d = {'1_account_id': '5', '1_qty_in': '10.01', '1_uom_in': '1', '2_account_id': '23', '2_qty_in': '2.01', '2_uom_in': '1','3_account_id': '23', '3_qty_in': '2.01', '3_uom_in': '1' ,'some_x':1,'some_y':0}
ans = {}
for key in d:
n,k = key.split('_', 1)
if n in ans:
ans[n][k] = d[key]
else:
ans[n] = {'account_id': 0, 'qty_in': 0, 'uom_in': 0}
ans[n][k] = d[key]
The above code produces the following output in which the entire output ans is a dictionary with the numbers as keys, and the values for each of the keys is also a dictionary, each containing 3 keys and corresponding values :
{'1': {'account_id': '5', 'qty_in': '10.01', 'uom_in': '1'},
'2': {'account_id': '23', 'qty_in': '2.01', 'uom_in': '1'},
'3': {'account_id': '23', 'qty_in': '2.01', 'uom_in': '1'},
'some': {'account_id': 0, 'qty_in': 0, 'uom_in': 0, 'x': 1, 'y': 0}}
Now to convert it into the list which you have shown in the desired output, use the follwing code. Here we convert the dictionary of dictionaries to a list containing dictionaries.
ans2 = []
for row in ans:
temp = {}
temp[row] = ans[row]
ans2.append(temp)
which produces the desired output :
[{'1': {'account_id': '5', 'qty_in': '10.01', 'uom_in': '1'}},
{'2': {'account_id': '23', 'qty_in': '2.01', 'uom_in': '1'}},
{'3': {'account_id': '23', 'qty_in': '2.01', 'uom_in': '1'}},
{'some': {'account_id': 0, 'qty_in': 0, 'uom_in': 0, 'x': 1, 'y': 0}}]
Hope this helps !
Mostafa.
You can run this code example to solve it:
example_dict = {'1_account_id': '5', '1_qty_in': '10.01', '1_uom_in': '1', '2_account_id': '23', '2_qty_in': '2.01', '2_uom_in': '1','3_account_id': '23', '3_qty_in': '2.01', '3_uom_in': '1' ,'some_x':1,'some_y':0}
desired_keys = ['account_id','qty_in','uom_in']
result = {}
for key,value in example_dict.items():
key_num, key_name = key.split('_', 1)
if key_name in desired_keys:
result.setdefault(key_num, {})[key_name] = value
print(result)
{'1': {'accountid': '5', 'qtyin': '10.01', 'uomin': '1'}, '2': {'accountid': '23', 'qtyin': '2.01', 'uomin': '1'}, '3': {'accountid': '23', 'qtyin': '2.01', 'uomin': '1'}, 'some': {'x': 1, 'y': 0}}
It will print (as you desired):
{'1': {'accountid': '5', 'qtyin': '10.01', 'uomin': '1'}, '2': {'accountid': '23', 'qtyin': '2.01', 'uomin': '1'}, '3': {'accountid': '23', 'qtyin': '2.01', 'uomin': '1'}, 'some': {'x': 1, 'y': 0}}
Tell me if you do not understand something.

How to calculate NRR from the list of dictionaries?

I'm trying to calculate Net run rate for the list containing dictionaries
suppose if list is
score = [{'dismissal': 'run out (Hardik Pandya)', 'balls': '92', 'name': 'Amla', 'fours': '5', 'six': '0', 'runs': '71'}, {'dismissal': 'c Kohli b Bumrah', 'balls': '32', 'name': 'Markram(c)', 'fours': '4', 'six': '1', 'runs': '32'}, {'dismissal': 'c Rohit b Hardik Pandya', 'balls': '5', 'name': 'Duminy', 'fours': '0', 'six': '0', 'runs': '1'}..........]
I'm trying to calculate NRR for these valuese which are dynamic they keep changing, I tried using enumerate but I can't figure out how to proceed further
dic= {k+str(i): v for i, x in enumerate(score, 1) for k, v in x.items()}
this will add indexes to the key of a dictionary how can I proceed after this, is there any other way its possible to achieve this?
By the way, to calculate NRR formula is = (runs/balls)*100, any assistance will be helpful.
expecting to get like this
dic = [{'dismissal1': 'run out (Hardik Pandya)', 'balls1': '92', 'name1': 'Amla', 'fours1': '5', 'six1': '0', 'runs1': '71','NRR1':'19.3'}, {'dismissal2': 'c Kohli b Bumrah', 'balls2': '32', 'name2': 'Markram(c)', 'fours2': '4', 'six2': '1', 'runs2': '32','NRR2':'44.3'}, {'dismissal3': 'c Rohit b Hardik Pandya', 'balls3': '5', 'name3': 'Duminy', 'fours3': '0', 'six3': '0', 'runs3': '1','NRR3':'45.3'}..........]

Python 3 Dictionary sorted with wrong output

I am currently doing an Assignment; however, I got some interesting output which confused me so much.
I am trying to sort the following dictionary:
result = {'A1': '9', 'A2': '14', 'A3': '16', 'A4': '0', 'B1': '53', 'B2': '267', 'B3': '75', 'B4': '22', 'C1': '19', 'C2': '407', 'C3': '171', 'C4': '56', 'C5': '10', 'D3': '47', 'D4': '34', 'D5': '10'}
My sorting code with Python 3 is the following : (only sorted by value)
sortedList = [v for v in sorted(result.values())]
The output is :
['0', '10', '10', '14', '16', '171', '19', '22', '267', '34', '407', '47', '53', '56', '75', '9']
which is not fully sorted. The output is quite strange.
Why it is happened like this?
I have used another dict to test like this:
testD = {'A':'5','B': '9','c': '8','d': '6'}
the output is right :
['5', '6', '8', '9']
Is there something wrong with my result dictionary or is there something I am missing?
Strings will be ordered with a lexical sort. To sort your data numerically, convert the values into integers first.
Strings are compared one character at a time, so '30' < '4' because '3' < '4'. You need to use a key parameter to get the comparison based on the numeric value, not the string characters.
Also, it's redundant to use a list comprehension on something that already returns a list.
sortedList = sorted(result.values(), key=int)
As the value of dictionary are string so there is lexical sorting based on ascii values.
As evident, you need the values to be sorted according to their integer values.
result = {'A1': '9', 'A2': '14', 'A3': '16', 'A4': '0', 'B1': '53', 'B2': '267', 'B3': '75', 'B4': '22', 'C1': '19', 'C2': '407', 'C3': '171', 'C4': '56', 'C5': '10', 'D3': '47', 'D4': '34', 'D5': '10'}
As mentioned in the comments by #AChampion, you can pass the sort value type by using key something like this :
sortedList = sorted(result.values(), key = int)
print(sortedList)
Or you can do something like this :
result_ints = dict((k,int(v)) for k,v in result.items())
sortedList = [str(v) for v in sorted(result_ints.values())]
print(sortedList)
Both of the above code snippets will result in :
['0', '9', '10', '10', '14', '16', '19', '22', '34', '47', '53', '56', '75', '171', '267', '407']
You can try this :
result = [{'A1': '9', 'A2': '14', 'A3': '16', 'A4': '0', 'B1': '53', 'B2': '267', 'B3': '75', 'B4': '22', 'C1': '19', 'C2': '407', 'C3': '171', 'C4': '56', 'C5': '10', 'D3': '47', 'D4': '34', 'D5': '10'}]
lst=[]
for item in result:
for key in item.keys():
lst.append(int(item.get(key)))
sortedList = [v for v in sorted(lst)]
print(sortedList)
Output: [0, 9, 10, 10, 14, 16, 19, 22, 34, 47, 53, 56, 75, 171, 267,
407]

append values to a dict in python

I have a list of dictionaries -
list1 = [{'id' : '1', 'b' : '2', 'c' : '3'}, {'id' : '4', 'b' : '5', 'c' : '6'}, {'id' : '7', 'b' : '8', 'c' : ''}]
Based on the value of c being null or not, I am making a call which returns -
list2 - {'d' : '30', 'id' : 1}, {'d': '25', 'id' : '4'}
Now I want to modify list1, so that the final list has the values of d for the ids which have c. For example -
list1 = [{'id' : '1', 'b' : '2', 'c' : '3', 'd' : '30'}, {'id' : '4', 'b' : '5', 'c' : '6', 'd' : '25'}, {'id' : '7', 'b' : '8', 'c' : ''}]
My approach -
for l in list2:
current_list = {}
for l2 in list1:
if l2['id'] == l['id']:
current_list = l2
break
if current_list:
current_list['d'] = l['d']
Here the actual dict is not getting modified. How can I modify the actual list? Also, is there a neater way to do this?
I'm not certain I understand what you are trying to accomplish. Your written description of your goal does not agree with you code. Based on the code, I'm guessing that you want to match up the data based on the id values.
# You've got some dicts.
dicts = [
{'id': '1', 'b': '2', 'c': '3'},
{'id': '4', 'b': '5', 'c': '6'},
{'id': '7', 'b': '8', 'c': ''},
]
# You've got some other dicts having the same IDs.
d_dicts = [
{'d': '30', 'id': '1'},
{'d': '25', 'id': '4'},
]
# Reorganize that data into a dict, keyed by ID.
dlookup = {d['id'] : d['d'] for d in d_dicts}
# Now add that lookup data to the main list of dicts.
for d in dicts:
i = d['id']
if i in dlookup:
d['d'] = dlookup[i]
Assuming mr FMc are correct, there is in python 3.5 a valid approach to merge dicts. Which in this case would led us to:
dicts = [
{'id': '1', 'b': '2', 'c': '3'},
{'id': '4', 'b': '5', 'c': '6'},
{'id': '7', 'b': '8', 'c': ''},
]
d_dicts = [
{'d': '30', 'id': '1'},
{'d': '25', 'id': '4'},
]
dicts = [{**d, **dict(*filter(lambda x: x["id"] == d["id"], d_dicts))} for d in dicts]
I like these kinda expressions instead of writing it all out, but it has the "benefit" of crashing instead of overwriting stuff when there is more then one dict with the same id. But my solution still overwrites values if there are duplicate keys silently. The inserted value being the value from whatever's second in the dict merge.

How to convert list into a dictionary by python

old_list = [ ['ID0', 'ID1'], ['4', '8'], ['5', '6'] ]
I want convert list to new list
key = ['id', 'frame', 'length']
new_list = [{'id': 'ID0', 'frame': '4', 'length': '5'}, {'id': 'ID1', 'frame': '8', 'length': '6'}]
Here's a one-line approach:
>>> [{'id':x, 'frame':y, 'length':z} for x,y,z in zip(*old_list)]
[{'length': '5', 'frame': '4', 'id': 'ID0'}, {'length': '6', 'frame': '8', 'id': 'ID1'}]
new_list=[]
for x,y,z in zip(old_list[0],old_list[1], old_list[2]):
dict = {'id' : x, 'frame' : y, 'length': z}
new_list.append(dict)

Categories

Resources