A shorter way?
Is there a shorter way instead of using column of 'elif'?
As there are no statements in Python that work like "switch" from C/Java/etc. there is not much that you can optimize there. What you can do though is reduce the number of conditions.
For example, your first statement checks if the variable is <= 20. The next elif then checks if it is > 20 and < 70, but you only need to check if it is < 70, because the previous if would have been run instead if it wasn't > 20 (i. e. if it was <= 20). That way you can reduce the number of comparisons you have to make by almost half.
EDIT: Coming to think of it, a switch statement wouldn't be helpful either.
A python dictionary can work like a switch statement in most cases. But with ranges, like that one, it doesn't help any more than a switch statement would.
If you turn the comparison into a consistent mathematical comparison, you could do something like:
COMPASS = ('N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'N') def compass_dir(degrees): return COMPASS[int((degrees+22.5)/45)]
Fun version of @onionradish's version (and works with any angle):
COMPASSV = 'NN SSS N' COMPASSH = ' EEE WWW' def compass_dir(degrees): octant = int((degrees+22.5)/45) % 8 return (COMPASSV[octant] + COMPASSH[octant]).strip()
The following code is a bit shorter than the one with the
elifs, but this is not necessarily better (it is more difficult to understand). Anyway, it was a fun exercise.
def name(x): compass = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'N' ] angles = [-20, 20, 70, 110, 160, 200, 250, 290, 340, 380] i = 0 while i<len(compass): if i%2==0: # Index is even if angles[i] <= x <= angles[i+1]: return compass[i] else: # Index is odd if angles[i] < x < angles[i+1]: return compass[i] i = i + 1 return "Error"
Note: I much prefer the solutions given by onionradish and henryiii (I myself thought of something similar), but these functions do not give exactly the same results than Dann's one, which does not use equally-sized sectors.
Python dict approach added to gist for completeness. I still like the onionradish solution best.
COMPASS = 'N NE E SE S SW W NW N'.split() # alternative approach to creating the list
To consider: try with values -1, 10000, 'a'.
That is a very awesome solution from onionradish, thank you.
We have a problem here... The output of the seven functions is not identical for the input value of 21!
(21, 'NE', 'N', 'N', 'NE', 'NE', 'NE', 'NE') # https://github.com/cclauss/compass-direction-bakeoff/issues/1
https://github.com/cclauss/compass-direction-bakeoff accepting pull requests to bring all 7 functions into agreement.