-3

I'd like to check if a Python string contains BOTH letter and number, but nothing else. In other words, strings like "A530", "D592" should return True, whereas strings like "ABCDE" (all letters), "000326" (all number), and "A339*加>" (alphanumeric but also has special characters) will return False.

I've seen a lot of sites that show how to check if string contains either letter or number, but not both. This site https://www.geeksforgeeks.org/python-program-to-check-if-a-string-has-at-least-one-letter-and-one-number/ shows how to check both letter and number, but they iterate through each character in the string, which is not very efficient and something I tried to avoid doing if possible.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
Stanleyrr
  • 858
  • 3
  • 12
  • 31
  • We have hundreds of questions about regexes to enforce inane password requirements; did you search before asking? – tripleee Dec 23 '20 at 06:22
  • Does this answer your question? [Does Python have a string 'contains' substring method?](https://stackoverflow.com/questions/3437059/does-python-have-a-string-contains-substring-method) – 23tux Dec 23 '20 at 10:34
  • Your title mentions the `_` character, but the question body says nothing about it. It's not clear what your actual requirements are. – user2357112 Dec 24 '20 at 06:33

3 Answers3

0

If those string are individual strings, you can use a regex to check that:

import re

re.match("^(?=.*[a-zA-Z])(?=.*[\d])[a-zA-Z\d]+$", "A530") # Will return an re.Match object
re.match("^(?=.*[a-zA-Z])(?=.*[\d])[a-zA-Z\d]+$", "A339*加>") # Will return None
re.match("^(?=.*[a-zA-Z])(?=.*[\d])[a-zA-Z\d]+$", "AAAA") # Will return None
re.match("^(?=.*[a-zA-Z])(?=.*[\d])[a-zA-Z\d]+$", "0000") # Will return None

Or Y
  • 2,088
  • 3
  • 16
  • it seems running re.match("^\w+$", "623") will also return an re.Match object, but that string doesn't have letter in it. – Stanleyrr Dec 23 '20 at 06:18
  • 1
    @Stanleyrr Oh I misread, Let me quickly fix that for you and edit my post – Or Y Dec 23 '20 at 06:19
  • 1
    @Stanleyrr Check out the updated version of the regex – Or Y Dec 23 '20 at 06:28
  • 1
    Thanks, @Or Y. This is better, except re.match("^(?=.*[wa-zA-Z])(?=.*[\d])[\w]+$", "567A_") would also return the object even though it shouldn't (there's an underscore sign in the string) – Stanleyrr Dec 23 '20 at 06:32
  • 1
    @Stanleyrr Edited again, now it won't accept underscores. – Or Y Dec 23 '20 at 14:27
0

Solution without regex :)

s=input()
print(not ((all(i.isdigit() for i in s) or (all(i.isalpha() for i in s)) or (any(not i.isalnum() for i in s)))))
Nanthakumar J J
  • 860
  • 1
  • 7
  • 22
0

If you don't prefer regex then here is the way.

All conditions checked separately. It is Pythonic and readable as well.

Code:

import string

lst = ["A530", "D592", "ABCDE", "000326", "A339*加>"]
str_ascii_digits = string.ascii_letters + string.digits
passed = [s for s in lst if 
            any(ch in string.ascii_letters for ch in s ) and 
            any(ch in string.digits for ch in s) and 
            all((ch in str_ascii_digits for ch in s))]
print(passed)

Output:

['A530', 'D592']
    
Aaj Kaal
  • 1,205
  • 1
  • 9
  • 8