pythonstringif-statementdigits

How to I check if a string contains only digits or "/" in Python?


I am trying to check if a string contains only digits or "/", to use as a form of validation, however I cannot find and way to do both. ATM I have this:

if variable.isdigit() == False:

This works for the digits, but I have not found a way to check also for the slashes.


Solution

  • There are many options, as showed here. A nice one would be list comprehensions.

    Let's consider two strings, one that satisfies the criteria, other that doesn't:

    >>> match = "123/456/"
    >>> no_match = "123a456/"
    

    We can check if a character of them matches by using isdigit() and comparation:

    >>> match[0].isdigit() or match[0] == '/'
    True
    

    But we want to know if all chars match. We can get a list of results by using list comprehensions:

    >>> [c.isdigit() or c == '/' for c in match]
    [True, True, True, True, True, True, True, True]
    >>> [c.isdigit() or c == '/' for c in no_match]
    [True, True, True, False, True, True, True, True]
    

    Note that the list of the non-matching string has False at the same position of the 'a' char.

    Since we want all chars to match, we can use the all() function. It expects a list of values; if at least one of them is false, then it returns false:

    >>> all([c.isdigit() or c == '/' for c in match])
    True
    >>> all([c.isdigit() or c == '/' for c in no_match])
    False
    

    Bonus points

    Put on a function

    You would be better to put it on a function:

    >>> def digit_or_slash(s):
    ...     return all([c.isdigit() or c == '/' for c in s])
    ... 
    >>> digit_or_slash(match)
    True
    >>> digit_or_slash(no_match)
    False
    

    Generator expressions

    Generator expressions tend to be more efficient:

    >>> def digit_or_slash(s):
    ...     return all(c.isdigit() or c == '/' for c in s)
    ... 
    

    But in your case it is probably negligible anyway.

    What about in?

    I would prefer to use the in operator, as below:

    >>> def digit_or_slash(s):
    ...     return all(c in "0123456789/" for c in s)
    

    Note that this is only one of the options. Sadly, your problem fails this Zen of Python recommendation (>>> import this):

    There should be one- and preferably only one -obvious way to do it.

    But that's ok, now you can choose whatever you prefer :)