0

What is the most pythonic way to merge two list dictionaries please? Say I have two list of dictionaries as:

sold=[
{'dept': '001', 'sku': 'foo', 'qty': 100},
{'dept': '002', 'sku': 'bar', 'qty': 200},
{'dept': '003', 'sku': 'baz', 'qty': 300}
]

returns=[
{'dept': '001', 'sku': 'foo', 'qty': 10},
{'dept': '002', 'sku': 'bar', 'qty': 20}
]

desired_output=[
{'dept': '001', 'sku': 'foo', 'sold': 100, 'return': 10},
{'dept': '002', 'sku': 'bar', 'sold': 200, 'return': 20},
{'dept': '003', 'sku': 'baz', 'sold': 300, 'return': 0}
]

The code below worked, but is there a more elegant/pythonic way to do this please

merge = []
for s in sold:
    found = False
    for r in returns:
        if (s.get('sku') == r.get('sku') and s.get('dept') == r.get('dept')):            
            merge.append({'sku': r.get('sku'), 'dept': r.get('dept'), 'sold': s.get('qty'), 'return': r.get('qty')})
            found = True
            break
    if not found:
        merge.append({'sku': s.get('sku'), 'dept': s.get('dept'), 'sold': s.get('qty'), 'return': 0})     

I have checked this post: How to merge lists of dictionaries, it doesn't give me exactly what I want:

  1. I need to merge by multiple keys, i.e. sku and dept
  2. I have to rename the qty to sold and return respectively from 2 lists of dictionaries.

I tried something like below but couldn't get it work:

result = [
    s['return'] = r['qty'] 
    for s in sold 
    for r in return 
    if s['sku'] == r['sku'] and s['dept'] == r['dept']]

Thanks

Community
  • 1
  • 1
Can Lu
  • 736
  • 2
  • 8
  • 17
  • 1
    I have a hard time believing that code worked. `return` is a keyword, and so can't be used as a variable name.. – DSM Feb 12 '14 at 04:03
  • sorry it's puedo code, I've just had it updated. ignore the vairable name please, the nested loop way does work, but it doesn't look very phythonic to me. – Can Lu Feb 12 '14 at 04:09

1 Answers1

1

This mutates the sold dictionary.

temp = {(cd["dept"], cd["sku"]):cd["qty"] for cd in returned}

for cd in sold:
    cd["sold"] = cd["qty"]
    del cd["qty"]
    cd["return"] = temp.get((cd["dept"], cd["sku"]), 0)

print sold

If you don't want to mutate it, you can use this

temp, result = {(cd["dept"], cd["sku"]):cd["qty"] for cd in returned}, []

for cd in sold:
    temp_dict = {}
    for k, v in cd.items():
        if k == "sold":
            temp_dict["sold"] = cd["qty"]
        else:
            temp_dict[k] = cd[k]
    temp_dict["return"] = temp.get((cd["dept"], cd["sku"]), 0)
    result.append(temp_dict)

print result

Output

[{'sku': 'foo', 'dept': '001', 'sold': 100, 'return': 10},
 {'sku': 'baz', 'dept': '002', 'sold': 200, 'return': 20},
 {'sku': 'foo', 'dept': '003', 'sold': 300, 'return': 0}]
thefourtheye
  • 233,700
  • 52
  • 457
  • 497
  • Thanks again thefourtheye, I like the 2nd approach. Just a minor thing, i guess you really meant: if k=="qty": temp_dict["sold"] = cd["qty"] ? – Can Lu Feb 12 '14 at 04:44