0
votes
\$\begingroup\$

I have two dictionaries that I need the keys to match and if they match i will get the value of the first dictionary and then get the value of 2nd dictionary and build a new dictionary out of those.

dic1 = {u'ShutterHours': 732, u'ShieldHours': 732, u'MaskHours': 28, u'TargetHours': 790, u'GndRingHours': 25}
dic2 = {u'ShutterHours': u'Shutter Hours', u'ShieldHours': u'Shield Hours', u'MaskHours': u'Mask Hours', u'TargetHours': u'Target Hours', u'GndRingHours': u'Ground Ring Hours'}

This is my code so far:

final = {}
for k,k2 in zip(dic1,dic2):
    if k == k2:
        final[dic2[k]] = dic1[k]

Expected output:

{u'Ground Ring Hours': 25, u'Shutter Hours': 732, u'Shield Hours': 732, u'Mask Hours': 28, u'Target Hours': 790}

This works fine but I'm a bit skeptical if this is the best and Pythonic way to do this.

\$\endgroup\$
2
  • \$\begingroup\$ What's the expected output for this example? Are you sure that it works? \$\endgroup\$ Commented Mar 31, 2016 at 21:47
  • \$\begingroup\$ edited the question @200_success \$\endgroup\$
    – ellaRT
    Commented Mar 31, 2016 at 21:49

1 Answer 1

2
votes
\$\begingroup\$

This mechanism is so fragile that I can't tell for sure what it is supposed to do. The main issue is that you can't reliably predict the order in which the keys of a dictionary will be enumerated. For example, this seems to work as you intend:

>>> dic1 = {u'ShutterHours': 732, u'ShieldHours': 732, u'MaskHours': 28, u'TargetHours': 790, u'GndRingHours': 25}
>>> dic2 = {u'ShutterHours': u'Shutter Hours', u'ShieldHours': u'Shield Hours', u'MaskHours': u'Mask Hours', u'TargetHours': u'Target Hours', u'GndRingHours': u'Ground Ring Hours'}
>>> list(zip(dic1, dic2))
[('ShutterHours', 'ShutterHours'), ('ShieldHours', 'ShieldHours'), ('GndRingHours', 'GndRingHours'), ('MaskHours', 'MaskHours'), ('TargetHours', 'TargetHours')]

However, if you insert one entry into dic2, the whole thing might fall apart:

>>> …
>>> dic2[''] = 'empty string'
>>> list(zip(dic1, dic2))
[('ShutterHours', 'ShutterHours'), ('ShieldHours', ''), ('GndRingHours', 'GndRingHours'), ('MaskHours', 'ShieldHours'), ('TargetHours', 'MaskHours')]

What you probably want is a dict comprehension.

final = {dic2[k]: v for k, v in dic1.items()}

Better variable names would make the code easier to understand as well (e.g. labels instead of dic2).

\$\endgroup\$
3
  • \$\begingroup\$ thank you for your suggestion, mainly those dictionaries should and will always have the same length. @200_success \$\endgroup\$
    – ellaRT
    Commented Mar 31, 2016 at 22:06
  • 1
    \$\begingroup\$ You still can't count on them to have any predictable iteration order. \$\endgroup\$ Commented Mar 31, 2016 at 22:06
  • \$\begingroup\$ You should at least use final = {dic2[k]: v for k, v in dic1.items() if k in dic2} for the cases where a key is in dic1 and not in dic2. \$\endgroup\$
    – Cilyan
    Commented Apr 1, 2016 at 16:11

Not the answer you're looking for? Browse other questions tagged or ask your own question.