5

I have two list :

list1 = [{"name":"xyz" ,"roll":"r" , "sap_id":"z"} , {"name":"pqr" ,"roll":"s" , "sap_id":"w"}]
list2 = [{"cn_number":"26455"} , {"cn_number":"26456"}]

I want a new list like:

new_list = [{"name":xyz ,"roll":"r" , "sap_id":"z","cn_number":"26455"} , {"name":"pqr" ,"roll":"s" , "sap_id":"w","cn_number":"26456"}]

I tried the following method:

new_list = [i.update(j) for i, j in zip(list1, list2)]

but got some nasty error

false
  • 10,264
  • 13
  • 101
  • 209
  • 13
    "but got some nasty error" doesn't help at all. For an analogy, if you go to your doctor, would you say "I got some nasty pain"? – AKX Jan 01 '22 at 01:44
  • I don't get an error. Maybe you meant a _bug_, whereby the new list is `[None, None]`, because `i.update(j)` updates `i` but doesn't return it. If you use `for i, j in zip(list1, list2): i.update(j)`, `list1` will now be the desired new list, but such mutation isn't good practice. – J.G. Jan 01 '22 at 12:25
  • I haven't tried that. – Animesh Singh Jan 03 '22 at 11:45

3 Answers3

11

This syntax works for python3.5+ to merge two dictionaries z = {**x, **y}

Python 3.7.0 (default, Jun 28 2018, 13:15:42)
>>> list1 = [{"name":"xyz" ,"roll":"r" , "sap_id":"z"} , {"name":"pqr" ,"roll":"s" , "sap_id":"w"}]
>>> list2 = [{"cn_number":"26455"} , {"cn_number":"26456"}]
>>> new_list = [{**i, **j} for i, j in zip(list1, list2)]
>>> new_list
[{'name': 'xyz', 'roll': 'r', 'sap_id': 'z', 'cn_number': '26455'}, {'name': 'pqr', 'roll': 's', 'sap_id': 'w', 'cn_number': '26456'}]

More information: How do I merge two dictionaries in a single expression (take union of dictionaries)?

Kamel
  • 1,856
  • 1
  • 15
  • 25
4

You can use the Python 3.5+ dict merging syntax:

new_list = [{**a, **b} for (a, b) in zip(list1, list2)]

results in

[
  {'name': 'xyz', 'roll': 'r', 'sap_id': 'z', 'cn_number': '26455'}, 
  {'name': 'pqr', 'roll': 's', 'sap_id': 'w', 'cn_number': '26456'},
]
AKX
  • 152,115
  • 15
  • 115
  • 172
2

An efficient way to do this is with collections.ChainMap which is made specifically for combining multiple dictionaries. Read more on the documentation here.

from collections import ChainMap

[dict(ChainMap(i,j)) for i,j in zip(list1, list2)]
[{'cn_number': '26455', 'name': 'xyz', 'roll': 'r', 'sap_id': 'z'},
 {'cn_number': '26456', 'name': 'pqr', 'roll': 's', 'sap_id': 'w'}]

NOTE: Depending on how you want to use each element of the updated list, you could use a generator and avoid using dict() over ChainMap object to still get what you need without using unnecessary memory! ChainMap gives you a single updatable view of the multiple dictionaries by still referencing the original objects.

#efficient way -

#EDITED: lesser keystrokes as suggested by @Kelly
g = map(ChainMap, list1, list2) 

#g = (ChainMap(i,j) for i,j in zip(list1, list2))

next(g).get('sap_id')
z
Akshay Sehgal
  • 18,741
  • 3
  • 21
  • 51