3

I have to validate that the string is either 4 or 6 digits. The string cannot contain any characters, only integers. Return true if it meets the condition else false.

I tried to create a list with acceptable digits and loop through the string and compare. If any part of the string is not in the acceptable list I will exit the loop and return false. If the running total is equal to 4 or 6 then it should be true. python code:

def validate(n):
   count = 0
   valid_list = list(range(10))
   for digit in pin:
      if digit not in valid_list:
         return False
      count += 1

I'm not sure why something like 1234 is being returned as False.

Amaresh S M
  • 2,936
  • 2
  • 13
  • 25
Ajaff
  • 73
  • 5
  • 4
    `if len(string) in (4, 6) and string.isdigit():`? I'm on phone so I can't edit your post and review your code to say why it didn't work, though – roganjosh Sep 03 '19 at 17:19
  • 2
    Presumably the OP actually wants [`isdecimal()` instead of `isdigit()`](https://stackoverflow.com/q/22789392). – jdehesa Sep 03 '19 at 17:24
  • Is a string like `0123` a valid input? – chepner Sep 03 '19 at 17:27
  • Would you consider 0012 a valid number for your use case? – Voo Sep 03 '19 at 17:29
  • 2
    I think you are passing 'n' as a string (which is why `for digit in n:` doesn't return an error), and char '1' != int 1 – Aryerez Sep 03 '19 at 17:31
  • 3
    Also, please be sure the code you post accurately reflects what you are having a problem with. The code you posted has an undefined `pin` variable (presumably meant to be the parameter of `validate`). – chepner Sep 03 '19 at 17:36
  • Related: [How can Python compare strings with integers?](https://stackoverflow.com/questions/40403108/how-can-python-compare-strings-with-integers) – wwii Sep 03 '19 at 18:38
  • 1
    It would have been shorter and simpler to do `valid_list = "0123456789"`. – ekhumoro Sep 03 '19 at 18:42

2 Answers2

3

How about with regex?

import re
str="03506"
pattern="[0-9]{4,6}"
prog=re.compile(pattern)
result=prog.match(str)    
if result:
    return True
else:
    return False

This matches digits that are between 4 and 6 characters long. If you mean you want to match those string that are 4 or 6 long, you can try

import re
str="03506"
pattern1="[0-9]{4}"
pattern2="[0-9]{6}"

if re.match(pattern1,str) or re.match(pattern2, str):
    return True
else:
    return False
Matt Cremeens
  • 4,951
  • 7
  • 38
  • 67
  • There's no real need to precompile the regular expression. – chepner Sep 03 '19 at 17:26
  • 3
    I'm almost certain that {4,6} means 4 to 6 repeats and not what the asker wants. And compiling a regex to be only used once is a very bad idea. – Voo Sep 03 '19 at 17:28
  • @Voo The expression gets compiled whether you call `re.compile` or not; the `re` module just maintains a cache of the most recently used regular expressions to avoid compiling them each time you use them. – chepner Sep 03 '19 at 17:31
  • 1
    The single pattern `[0-9]{4}([0-9]{2})?` would also suffice. – chepner Sep 03 '19 at 17:33
  • @chepner Really? Haven't looked at pythons regex implementation but that's rather strange - other libraries don't do this. – Voo Sep 03 '19 at 17:46
  • What do other libraries have to do with the way the `re` module is *documented* to handle regular expressions? – chepner Sep 03 '19 at 17:51
  • 1
    @chepner It actually needs to be `^[0-9]{4}([0-9]{2})?$`, otherwise strings like "123456789" will match. (Alternatively, for python >= 3.4, [fullmatch](https://docs.python.org/3/library/re.html#re.fullmatch) could be used instead of `match`). – ekhumoro Sep 03 '19 at 18:30
  • why would it be a *very bad idea*? at worst, it's a bit of pointless optimization and a bit of code smell. your claim sounds more alarmist than that. – JL Peyret Sep 03 '19 at 19:03
  • @JL I was thinking of other languages where compiling a regex takes orders of magnitudes longer than simply "interpreting" it for a good speedup the following times (also no caching in say .net or Java that I'm aware of). With the cache and less optimizations being done it's not that bad (assuming compile checks its cache first but that seems a reasonable assumption). Still the cache isn't limitless, so not using a local variable, but storing it elsewhere is prudent. – Voo Sep 05 '19 at 15:35
1

I'm not sure why something like 1234 is being returned as False.

Python never implicitly converts between integers and strings and comparisons between integers and strings are always false.

"valid_list" is a list of integers, but "digit" is a string, so you will never find anything in your list.

plugwash
  • 9,724
  • 2
  • 38
  • 51
  • Now I see the error. Thanks. Perhaps the easiest is: if len(string) in (4, 6) and string.isdigit() but to correct my error just change the valid_list = '0123456789' so now string is compared with string. – Ajaff Sep 03 '19 at 20:41