1

I'm looking for a concise way of taking two dicts that have a common key/value, and copying a key and value into one of the dicts. Example:

d1 = [{'name': 'john', 'uid': 'ax01', 'phone': '555-555-5555'},
    {'name': 'jane', 'uid': 'ax02', 'phone': '555-555-5555'},
    {'name': 'jimmy', 'uid': 'ax03', 'phone': '555-555-5555'}]

d2 = [{'uid': 'ax01', 'orderid': '9999', 'note': 'testing this'},
      {'uid': 'ax02', 'orderid': '6666', 'note': 'testing this'},
      {'uid': 'ax03', 'orderid': '7777', 'note': 'testing this'}]

Here uid is the key that I want to use to then copy the orderid key and the value for that matching data point. In the end I'd get something like:

output = [
    {'name': 'john', 'uid': 'ax01', 'phone': '555-555-5555', 'orderid': '9999'},
    {'name': 'jane', 'uid': 'ax02', 'phone': '555-555-5555', 'orderid': '6666'},
    {'name': 'jimmy', 'uid': 'ax03', 'phone': '555-555-5555', 'orderid': '7777'}
]

Where the orderid is pulled into d1. I'm looking for the pythonic way if at all possible.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
bryan
  • 1,031
  • 2
  • 17
  • 36

2 Answers2

5

You can use dict() to copy one dictionary and pass in the extra key. You need to create a mapping from uid to orderid first though:

uid_to_orderid = {d['uid']: d['orderid'] for d in d2}
output = [dict(d, orderid=uid_to_orderid[d['uid']]) for d in d1]

This assumes that you want to leave the dictionaries in d1 untouched otherwise. Other assumptions made are that uid values are unique, and that all uid values in d1 are present in d2.

Demo:

>>> d1 = [{'name': 'john', 'uid': 'ax01', 'phone': '555-555-5555'},
...     {'name': 'jane', 'uid': 'ax02', 'phone': '555-555-5555'},
...     {'name': 'jimmy', 'uid': 'ax03', 'phone': '555-555-5555'}]
>>> d2 = [{'uid': 'ax01', 'orderid': '9999', 'note': 'testing this'},
...       {'uid': 'ax02', 'orderid': '6666', 'note': 'testing this'},
...       {'uid': 'ax03', 'orderid': '7777', 'note': 'testing this'}]
>>> uid_to_orderid = {d['uid']: d['orderid'] for d in d2}
>>> [dict(d, orderid=uid_to_orderid[d['uid']]) for d in d1]
[{'orderid': '9999', 'phone': '555-555-5555', 'name': 'john', 'uid': 'ax01'}, {'orderid': '6666', 'phone': '555-555-5555', 'name': 'jane', 'uid': 'ax02'}, {'orderid': '7777', 'phone': '555-555-5555', 'name': 'jimmy', 'uid': 'ax03'}]
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
0

Great answer @Martijn Pieters

I can't think of a clever way to protect against missing data other something brutish like this:

d1 = [{'name': 'john', 'uid': 'ax01', 'phone': '555-555-5555'},
     {'name': 'jane', 'uid': 'ax02', 'phone': '555-555-5555'},
     {'name': 'jimmy', 'uid': 'ax03', 'phone': '555-555-5555'},
     {'name': 'jack', 'uid': 'ax04', 'phone': '555-555-5555'},
    {'name': 'joan', 'uid': 'ax05', 'phone': '555-555-5555'}]
d2 = [{'uid': 'ax01', 'orderid': '9999', 'note': 'testing this'},
       {'uid': 'ax02', 'orderid': '6666', 'note': 'testing this'},
       {'uid': 'ax03', 'orderid': '6666', 'note': 'testing this'},
       {'uid': 'ax05', 'orderid-not-here': '7777', 'note': 'testing this'}]

def get_orderid(search):
    match = [x for x in d2 if x['uid']==search]
    if len(match) == 0:
        return 'None'
    else:
        return match[0].get('orderid','None')


[dict(d, orderid=get_orderid(d['uid'])) for d in d1]


[ {'name': 'john', 'orderid': '9999', 'phone': '555-555-5555', 'uid': 'ax01'},
  {'name': 'jane', 'orderid': '6666', 'phone': '555-555-5555', 'uid': 'ax02'},
  {'name': 'jimmy', 'orderid': '6666', 'phone': '555-555-5555', 'uid': 'ax03'},
  {'name': 'jack', 'orderid': 'None', 'phone': '555-555-5555', 'uid': 'ax04'},
  {'name': 'joan', 'orderid': 'None', 'phone': '555-555-5555', 'uid': 'ax05'}]

`
aheld
  • 106
  • 3