4

I am trying to check that a string contains only / and digits, 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.

L3viathan
  • 26,748
  • 2
  • 58
  • 81
HipsterRules
  • 67
  • 1
  • 1
  • 9

6 Answers6

9

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 :)

Community
  • 1
  • 1
brandizzi
  • 26,083
  • 8
  • 103
  • 158
4

You could use the following regex.

import re

matched = re.match(r'^-?[0-9/]+$', '01/02/2016')
if matched:
    print 'Matched integers with slashes'
DominicEU
  • 3,585
  • 2
  • 21
  • 32
3

Use a regular expression:

import re
if re.match("[0-9/]+$", variable):
    pass # do something

re.match checks whether the variable matches the expression from the beginning on. The expression consists of the character class [0-9/] (numbers and the slash), a + (meaning one or more times), and a dollar symbol, which stands for the line end, so it makes sure the string not only starts with numbers (or slash), but also keeps matching the character class until the end.

L3viathan
  • 26,748
  • 2
  • 58
  • 81
0

you can use for loop to check char-by-char

def check(text):

   for char in text:
       if not (char.isdigit() or char == '/'):
           return false

   return true

if check(you_text):
    print("OK")

If you will need different chars you can use list or text with allowed chars - similar to this:

def check(text):

   for char in text:
       if char not in "0123456789/":
           return false

   return true
furas
  • 134,197
  • 12
  • 106
  • 148
  • 1
    You could make the `"0123456789/"` test string into a `frozenset` for faster testing... but I suspect that a regex may be faster here, due to the relatively slow speed of a Python loop. – PM 2Ring Feb 01 '16 at 13:37
0

Just another idea.

>>> set('01/02/2016') <= set('0123456789/')
True
>>> set('01/02 2016') <= set('0123456789/')
False
Stefan Pochmann
  • 27,593
  • 8
  • 44
  • 107
0

You could also do this using list comprehension and the any() function:

In [1]: mystring = '01/02/2016'

In [2]: all(c in '0123456789/' for c in mystring)
Out[2]: True
DainDwarf
  • 1,651
  • 10
  • 19