1

I'm trying to build a dict comprehension that does an insert and takes a slice.
Does anybody know how to do this, or even is this is possible at all?
I'm trying to get the same output in cprd with a dict comprehension, as in newd with a for loop.

Code (Python 3.6.1)

# Initializations
hline = "-"*80
h = ['H1', 'H2', 'H3', 'H4']
d = {'A': [['Y1', 'Y2', 'Y3', 'Y4'], [-3.4, 15.9, 'NA', 6.0], [-3.4, 4.2, -7.4, 6.3], [22.7, 7.4, 2.8, 'NA']], 'B': [['Y1', 'Y2', 'Y3', 'Y4'], [-45.8, -10.7, 'NA', 'NA'], [5.4, 12.7, 19.2, 20.3], [22.7, 7.4, 2.8, 'NA']], 'C': [['Y1', 'Y2', 'Y3', 'Y4'], [-10.5, 32.8, 'NA', 'NA'], [5.4, 12.7, 19.2, 20.3], [22.7, 7.4, 2.8, 'NA']]}
print(f"h = {h}")
print(f"d = {d}")
print(hline)

# Without dict/list comprehension
newd = {}
for key,value in d.items():
    value.insert(1,h)
    newd[key] = value[1:]
print(f"newd = {newd}")
print(hline)

# Re-Initializations
d = {'A': [['Y1', 'Y2', 'Y3', 'Y4'], [-3.4, 15.9, 'NA', 6.0], [-3.4, 4.2, -7.4, 6.3], [22.7, 7.4, 2.8, 'NA']], 'B': [['Y1', 'Y2', 'Y3', 'Y4'], [-45.8, -10.7, 'NA', 'NA'], [5.4, 12.7, 19.2, 20.3], [22.7, 7.4, 2.8, 'NA']], 'C': [['Y1', 'Y2', 'Y3', 'Y4'], [-10.5, 32.8, 'NA', 'NA'], [5.4, 12.7, 19.2, 20.3], [22.7, 7.4, 2.8, 'NA']]}

# Tryout with dict comprehension
cprd = {key:value[1:] for key,value in d.items()}
print(f"cprd = {cprd}")
print(hline)

Output

h = ['H1', 'H2', 'H3', 'H4']
d = {'A': [['Y1', 'Y2', 'Y3', 'Y4'], [-3.4, 15.9, 'NA', 6.0], [-3.4, 4.2, -7.4, 6.3], [22.7, 7.4, 2.8, 'NA']], 'B': [['Y1', 'Y2', 'Y3', 'Y4'], [-45.8, -10.7, 'NA', 'NA'], [5.4, 12.7, 19.2, 20.3], [22.7, 7.4, 2.8, 'NA']], 'C': [['Y1', 'Y2', 'Y3', 'Y4'], [-10.5, 32.8, 'NA', 'NA'], [5.4, 12.7, 19.2, 20.3], [22.7, 7.4, 2.8, 'NA']]}
--------------------------------------------------------------------------------
newd = {'A': [['H1', 'H2', 'H3', 'H4'], [-3.4, 15.9, 'NA', 6.0], [-3.4, 4.2, -7.4, 6.3], [22.7, 7.4, 2.8, 'NA']], 'B': [['H1', 'H2', 'H3', 'H4'], [-45.8, -10.7, 'NA', 'NA'], [5.4, 12.7, 19.2, 20.3], [22.7, 7.4, 2.8, 'NA']], 'C': [['H1', 'H2', 'H3', 'H4'], [-10.5, 32.8, 'NA', 'NA'], [5.4, 12.7, 19.2, 20.3], [22.7, 7.4, 2.8, 'NA']]}
--------------------------------------------------------------------------------
cprd = {'A': [[-3.4, 15.9, 'NA', 6.0], [-3.4, 4.2, -7.4, 6.3], [22.7, 7.4, 2.8, 'NA']], 'B': [[-45.8, -10.7, 'NA', 'NA'], [5.4, 12.7, 19.2, 20.3], [22.7, 7.4, 2.8, 'NA']], 'C': [[-10.5, 32.8, 'NA', 'NA'], [5.4, 12.7, 19.2, 20.3], [22.7, 7.4, 2.8, 'NA']]}
--------------------------------------------------------------------------------
Bjorn Mistiaen
  • 6,459
  • 3
  • 18
  • 42

1 Answers1

3

You can use list concatenation to create the desired values:

{key:[h]+value[1:] for key,value in d.items()}
# {'A': [['H1', 'H2', 'H3', 'H4'], [-3.4, 15.9, 'NA', 6.0], [-3.4, 4.2, -7.4, 6.3], [22.7, 7.4, 2.8, 'NA']], 'B': [['H1', 'H2', 'H3', 'H4'], [-45.8, -10.7, 'NA', 'NA'], [5.4, 12.7, 19.2, 20.3], [22.7, 7.4, 2.8, 'NA']], 'C': [['H1', 'H2', 'H3', 'H4'], [-10.5, 32.8, 'NA', 'NA'], [5.4, 12.7, 19.2, 20.3], [22.7, 7.4, 2.8, 'NA']]}

Note that:

  • it returns the exact same data as newd
  • it does not mutate d

In your example, d was changed after having defined newd. Is it a bug or a feature? :)

Community
  • 1
  • 1
Eric Duminil
  • 52,989
  • 9
  • 71
  • 124
  • 1
    It depends on whether the source dictionary is supposed to be mutated, which... I can't tell? I'd hope not? – mwchase May 09 '17 at 20:35
  • If the mutation *is deliberate* then `for v in d.values(): v[0] = h` is the way to go instead of inserting/slicing... – Jon Clements May 09 '17 at 20:48
  • The source dict is not supposed to be mutated, so this is a perfect solution :) Not sure what you mean by your "is it a bug or a feature?" question. – Bjorn Mistiaen May 09 '17 at 21:10
  • @BjornMistiaen: It's a common saying. Sometimes, a user or another developer might be intrigued by an unexpected behaviour (= a bug), but the original developer might have a perfectly good reason for this behaviour (= a feature). – Eric Duminil May 09 '17 at 21:14