How to update list of dictionaries using another list of dictionaries?

Viewed 1290

I have two lists as shown below. I want to update the new list using the old list. The criteria to update the new list are matching values for name in old list. What is the best way to do it?

Input

old_list = [{'age': 35, 'name': 'james'}, {'age': 42, 'name': 'bob'}]

new_list = [{'name': 'peter'}, {'name': 'james'}, {'age': 50, 'name': 'bob'}]

Expected Output

[{'name': 'peter'}, {'age': 35, 'name': 'james'}, {'age': 42, 'name': 'bob'}]

Edit: Adding my solution

One solution that I know to solve this using multiple loops and if conditions. It is not the compete solution as I need to handle multiple scenarios like where key is not present etc.

for x in new_col_list:
    for y in old_col_list:
        if x['name'] == y['name']:
            x['age'] = y['age']
            continue

print new_col_list
1 Answers

You need a structure that will allow you to do the lookup of items in one list from the other. A dictionary provides such a structure:

lookup = {x['name']: x for x in new_list}
lookup.update({x['name']: x for x in old_list})

You can then convert back to a list if you really want to:

result = list(lookup.values())

In Python 3.6+, the order of the values will be all the elements of the new list, followed by all the missing elements added from the old list in the order they were in the old list. For older versions of Python, the same can be achieved by collections.OrderedDict:

lookup = OrderedDict((x['name'], x) for x in new_list)
lookup.update((x['name'], x) for x in old_list)

Without the ordering, the result of dict.values() will be in arbitrary order, and may change between runs of the interpreter.

Appendix

Any time you see a dictionary comprehension, it is functionally equivalent to a for loop. Here is the "expanded" version of the first suggested code:

lookup = {}
for d in new_list:
    lookup[d['name']] = d
for d in old_list:
    lookup[d['name']] = d
Related