i have a simple task but not able to figure it out.
a = [{'name': 'Helen', 'age': '12', 'total_money':'12000'}, {'name': 'Victor', 'age':'20', 'total_money': '32999'}]
b = [{'name': 'Helen', 'age': '12', 'total_gold':'14'}]
I want to mere to list above, if the value of name
and age
is the same then combine it together. if not the same then leave it as it is.
expected output
output = [{'name': 'Helen', 'age': '12', 'total_money':'12000', 'total_gold':'14'}, {'name': 'Victor', 'age':'20', 'total_money': '32999'}]
this is what i have tried so far (not working)
c = a b
data = {}
for item in c:
key = item["name"] '-' item["age"]
if key in data:
if data[key]["total_money"] in data[key]:
data[key]["total_gold"] = item["total_gold"]
else:
data[key]["total_money"] = item["total_money"]
else:
data[key] = item
data[key]["total_money"] = item['total_money'] if 'total_money' in item else 0
data[key]["total_gold"] = item['total_gold'] if 'total_gold' in item else 0
i have a feeling that i am overthinking. any suggestion would be appreciate. Thank you.
CodePudding user response:
Seems like you want to merge two dictionaries, which can be done like so:
a = {'name': 'Helen', 'age': '12', 'total_money':'12000'}
b = {'name': 'Helen', 'age': '12', 'total_gold':'14'}
z = {**a, **b}
z
{'name': 'Helen', 'age': '12', 'total_money': '12000', 'total_gold': '14'}
If you'd like to maintain the list structure (assuming you plan to have multiple dictionaries as elements of these lists):
a = [{'name': 'Helen', 'age': '12', 'total_money':'12000'}]
b = [{'name': 'Helen', 'age': '12', 'total_gold':'14'}]
z = []
for i in range(len(a)):
z.append({**a[i], **b[i]})
EDIT:
z = []
for ele in a:
for piece in b:
if ele["name"] == piece["name"] and ele["age"] == piece["age"]:
z.append({**ele, **piece})
else:
z.append(ele)
CodePudding user response:
Solution
This is a good opportunity to learn how to use itertools.groupby()
:
import itertools
def sort_help(d: dict) -> tuple:
return d["name"], d["age"]
merged = []
for _, group in itertools.groupby(sorted(a b, key=sort_help), key=sort_help):
merged_dict = {}
for d in group:
merged_dict.update(d)
merged.append(merged_dict)
Output:
[{'name': 'Helen', 'age': '12', 'total_money': '12000', 'total_gold': '14'},
{'name': 'Victor', 'age': '20', 'total_money': '32999'}]
Explanation
This works by first concatenating your lists of dictionaries, and then sorting them by name, age
tuples:
In [6]: a b
Out[6]:
[{'name': 'Helen', 'age': '12', 'total_money': '12000'},
{'name': 'Victor', 'age': '20', 'total_money': '32999'},
{'name': 'Helen', 'age': '12', 'total_gold': '14'}]
In [7]: both_in_order = sorted(a b, key=sort_help)
In [8]: both_in_order
Out[8]:
[{'name': 'Helen', 'age': '12', 'total_money': '12000'},
{'name': 'Helen', 'age': '12', 'total_gold': '14'},
{'name': 'Victor', 'age': '20', 'total_money': '32999'}]
Then groupby groups the dictionaries into groups of matching name, age
tuples:
In [9]: for _, g in itertools.groupby(both_in_order, key=sort_help):
...: print(list(g))
...:
[{'name': 'Helen', 'age': '12', 'total_money': '12000'}, {'name': 'Helen', 'age': '12', 'total_gold': '14'}]
[{'name': 'Victor', 'age': '20', 'total_money': '32999'}]
From there, each group's dictionaries are merged into one.
Advantages
This method also has the benefit of being "extensible"; you could add more criteria for what dictionaries should merge by simply modifying the sort_help
function:
[{'name': 'Victor', 'age': 30, 'occupation': 'farmer', 'total_money': 1871},
{'name': 'Helen', 'age': 30, 'occupation': 'adventurer', 'total_gold': 8026},
{'name': 'Helen', 'age': 30, 'occupation': 'farmer', 'total_money': 7279},
{'name': 'Victor', 'age': 20, 'occupation': 'farmer', 'total_gold': 9762},
{'name': 'Victor', 'age': 20, 'occupation': 'farmer', 'total_money': 2853},
{'name': 'Helen', 'age': 30, 'occupation': 'adventurer', 'total_gold': 6002},
{'name': 'Victor', 'age': 20, 'occupation': 'farmer', 'total_gold': 582},
{'name': 'Helen', 'age': 30, 'occupation': 'adventurer', 'total_money': 8632},
{'name': 'Victor', 'age': 30, 'occupation': 'adventurer', 'total_gold': 6528},
{'name': 'Helen', 'age': 30, 'occupation': 'adventurer', 'total_money': 4101}]
By adding "occupation" to sort_help()
, we can very easily now group the dictionaries by all three criteria:
def sort_help(d: dict) -> tuple:
return d["name"], d["age"], d["occupation"]
Output:
[{'name': 'Helen', 'age': 30, 'occupation': 'adventurer', 'total_money': 4101, 'total_gold': 8026},
{'name': 'Helen', 'age': 30, 'occupation': 'farmer', 'total_money': 7279},
{'name': 'Victor', 'age': 20, 'occupation': 'farmer', 'total_gold': 9762, 'total_money': 2853},
{'name': 'Victor', 'age': 30, 'occupation': 'adventurer', 'total_gold': 6528},
{'name': 'Victor', 'age': 30, 'occupation': 'farmer', 'total_money': 1871}]
You can also very easily come up with a custom merging function which would, for example, add total_money
instead of overwrite.
CodePudding user response:
I re-wrote your function:
for item in c:
key = item["name"] '-' item["age"]
if key not in data:
data[key] = item
if "total_gold" in item:
data[key]["total_gold"] = item["total_gold"]
if "total_money" in item:
data[key]["total_money"] = item["total_money"]
if total_gold or total_money is written twice for the same "key" is will user the last value
output: [{'name': 'Helen', 'age': '12', 'total_money': '12000', 'total_gold': '14'}, {'name': 'Victor', 'age': '20', 'total_money': '32999'}]
CodePudding user response:
just iterate over the dictionaries, creating a new dictionary with the values. if the value is a dup it will continue:
a = {'name': 'Helen', 'age': '12', 'total_money':'12000'}
b = {'name': 'Helen', 'age': '12', 'total_gold':'14'}
c={}
for k,v in a.items():
c[k]=v
for k,v in b.items():
c[k]=v
print(c)
#{'name': 'Helen', 'age': '12', 'total_money': '12000', 'total_gold': '14'}