Home > other >  Merge two list in python
Merge two list in python

Time:10-06

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 ageis 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'}
  
  • Related