1

I have this long if statement to see if a string is equal to any number up to 9. But it is so long and takes a lot of space. Is there any way to make it shorter and cleaner? I'm new to programming.

if calculated == "1" or calculated == "2" or calculated == "3" or calculated == "4" or calculated == "5" or calculated == "6" or calculated == "7" or calculated == "8" or calculated == "9":
Mehrdad Pedramfar
  • 10,941
  • 4
  • 38
  • 59
Erik77
  • 109
  • 4
  • 12

3 Answers3

8

Yes, try this:

if calculated in ['1','2','3',...,'9']:
    # do

or you can do this:

if calculated in [str(i) for i in range(1, 10)]:
    # do

also this way is possible too:

if calculated in list(map(str, range(1, 10))):
   # do
Mehrdad Pedramfar
  • 10,941
  • 4
  • 38
  • 59
  • Yeah ok! Thanks the first one seems the easiest, but i will keep the others in mind! Thanks again! – Erik77 Nov 10 '18 at 08:51
  • @Erik77 your welcome. if you find my answer helpful please check the green one beside the question. – Mehrdad Pedramfar Nov 10 '18 at 08:52
  • 1
    In Python 3.x it should be simple a `if calculated in '1,2,3,4':` , 3.2 and newer will recognise this as an immutable constant. This is the fastest option for newer code. – Karn Kumar Nov 10 '18 at 09:01
  • 1
    you don't need to force iteration, even in python 3. Just use `calculated in map(str, range(1, 10))` – Jean-François Fabre Nov 10 '18 at 09:05
  • 1
    @pygo its an O(n) test - predefining a set of 1char strings and testing that is O(1) so faster – Patrick Artner Nov 10 '18 at 09:05
  • 1
    your last 2 method profit from doing the conversion _outside_ the testing code itself - consider using this in a tight loop - you would recreate and recreate and recreate and reacreate (you get it) the list you look into. Also: list membership testing is O(n) (if you find it in the last possible place) whereas `set` - testing is O(1) constant. Especially if you reuse the test, use `set`. – Patrick Artner Nov 10 '18 at 09:08
  • 1
    This is the [link](https://docs.python.org/3/whatsnew/3.2.html#optimizations) for immutable constants.. – Karn Kumar Nov 10 '18 at 09:12
  • 1
    @pygo - I dacor with `{"1","2","3",...,"9"}` - but you are just providing a string - wich is essentially an iterable. the optimisation is about recognizing a `{....}` as frozenset instead normal set if used in a condition - not about splitting your string at `,` and creating a `frozenset` from it. Or is it? Thanks for the link, gotta remember that one - I would have thought pre-creating the set is faster then inlining it. – Patrick Artner Nov 10 '18 at 09:16
  • @PatrickArtner, well said. – Karn Kumar Nov 10 '18 at 09:19
3

This smells like an XY problem. If you know your string is a number, you should cast it to a number and use integer based logic:

if 1 <= int(calculated) <= 9:
    pass

But if that doesn’t work for some reason, your logic could be simplified to checking a range:

if calculated in (str(n) for n in range(1, 10)):
    pass
Michael Leonard
  • 1,693
  • 20
  • 18
2

Or, say, in this simple case,

try:
    if int(calculated) in range(1, 10):

Or vice versa:

if calculated in map(str, range(1, 10)):
bipll
  • 11,747
  • 1
  • 18
  • 32
  • 1
    thumbs up for the int conversion which allows O(1) testing in `range`. In that case, go further and use `if 1 <= int(calculated) < 10` which is even faster because it doesn't create a range object :) – Jean-François Fabre Nov 10 '18 at 09:06
  • Sure, I've thought about posting simple comparison but considered it not generic enough. :) – bipll Nov 10 '18 at 12:01