2

I wanted to implement if elif and else inside a list comprehension and in this stackoverflow answer I found a way of doing the same.

So let me explain what the issue is:

As per the answer, the dict.get() can be used in following way to use conditionals in list comprehension:

>>> l = [1, 2, 3, 4, 5]
>>> d = {1: 'yes', 2: 'no'}
>>> [d.get(x, 'idle') for x in l]
['yes', 'no', 'idle', 'idle', 'idle']

Seems nice and good. But I am running into a different kind of problem. So I need to use the same method to work with the index of some other list. Allow me to explain:

perc = np.array([0, 0.25, 0.5, 0.75, 1])

d= {0: 0, len(perc):1}

result = [d.get(x, (perc[x-1]+perc[x])/2) for x in range(len(perc)+1)]

So in short I want my output to be 0 and 1 for x being 0 and len(perc), or else average of previous value and current value.

Now, this is giving me an error:

IndexError: index 5 is out of bounds for axis 0 with size 5

My question is, wasn't dict.get(key[, default])defined as:

Return the value for key if key is in the dictionary, else default. If default is not given, it defaults to None, so that this method never raises a KeyError.

Now clearly 5 as a key is in the dictionary as len(perc)=5, then why the default condition is being checked first, which obviously will give an error as there is no 5th index in the array perc.

Edit

As mentioned in the comment by Klaus, The expression is evaluated before .get() is called. If that's the case and nothing can be done about this, then is there any other way I can achieve this without using loops?

Amit Amola
  • 2,301
  • 2
  • 22
  • 37
  • The error is not raised by accesding the dictionary key but by accessing the array. There is no index `5` in a 5 item array. – Klaus D. Dec 27 '19 at 10:31
  • Hey Klaus, I've already mentioned that in my question, that it is accessing the 5th index from array. My question is, as per the definition of dict.get(), shouldn't it check the dictionary first where 5 as a key is already present. Because in that case, it won't need to check the default. – Amit Amola Dec 27 '19 at 10:33
  • The expression is evaluated before `.get()` is called. – Klaus D. Dec 27 '19 at 10:36
  • In that case, isn't the way it's defined in the docs.python wrong? It says: Return the value for key if key is in the dictionary, else default. – Amit Amola Dec 27 '19 at 10:37
  • No, it is correct. The default is the *result* of the *evaluated* expression. – Klaus D. Dec 27 '19 at 10:47

1 Answers1

1

do you want like this?

import numpy as np
perc = np.array([0, 0.25, 0.5, 0.75, 1])
d= {0: 0, len(perc):1}
result = [d.get(x, (lambda y: ((perc[y-1]+perc[y])/2) if y < len(perc) else 99999)(x)) for x in range(len(perc)+8)]
print(result)
#[0, 0.125, 0.375, 0.625, 0.875, 1, 99999, 99999, 99999, 99999, 99999, 99999, 99999]
joonghyup cha
  • 624
  • 3
  • 12
  • Yup works perfectly. I should've thought of using lambda. Silly me. I've upvoted. I'll wait for someone else to answer as well, to see if there is more elegant way or method; if not, I'll accept this as the answer. – Amit Amola Dec 27 '19 at 11:44