Input validation (Python) - python

For input I need to have a string that contains both numbers and letters or only letters. Atm my code works with these conditions, but how can I add that input must not consist of punctuation marks?
nimi = input("...name: ")
while name.isalnum == True or name.isnumeric():
name = input("...name: ")

It's better to use regex.
if re.match(r'^(?!\d+$)[\da-zA-Z]+$', pass):

As stated above, using regex is better. But the below condition will work for you. Use string.punctuation to take count of all the punctuations.
import string
while(name.isalnum() or name.isalpha()) and not any(i in string.punctuation for i in name):

Related

How I can use regex to remove repeated characters from string

I have a string as follows where I tried to remove similar consecutive characters.
import re
input = "abccbcbbb";
for i in input :
input = re.sub("(.)\\1+", "",input);
print(input)
Now I need to let the user specify the value of k.
I am using the following python code to do it, but I got the error message TypeError: can only concatenate str (not "int") to str
import re
input = "abccbcbbb";
k=3
for i in input :
input= re.sub("(.)\\1+{"+(k-1)+"}", "",input)
print(input)
The for i in input : does not do what you need. i is each character in the input string, and your re.sub is supposed to take the whole input as a char sequence.
If you plan to match a specific amount of chars you should get rid of the + quantifier after \1. The limiting {min,} / {min,max} quantifier should be placed right after the pattern it modifies.
Also, it is more convenient to use raw string literals when defining regexps.
You can use
import re
input_text = "abccbcbbb";
k=3
input_text = re.sub(fr"(.)\1{{{k-1}}}", "", input_text)
print(input_text)
# => abccbc
See this Python demo.
The fr"(.)\1{{{k-1}}}" raw f-string literal will translate into (.)\1{2} pattern. In f-strings, you need to double curly braces to denote a literal curly brace and you needn't escape \1 again since it is a raw string literal.
If I were you, I would prefer to do it like suggested before. But since I've already spend time on answering this question here is my handmade solution.
The pattern described below creates a named group named "letter". This group updates iterative, so firstly it is a, then b, etc. Then it looks ahead for all the repetitions of the group "letter" (which updates for each letter).
So it finds all groups of repeated letters and replaces them with empty string.
import re
input = 'abccbcbbb'
result = 'abcbcb'
pattern = r'(?P<letter>[a-z])(?=(?P=letter)+)'
substituted = re.sub(pattern, '', input)
assert substituted == result
Just to make sure I have the question correct you mean to turn "abccbcbbb" into "abcbcb" only removing sequential duplicate characters. Is there a reason you need to use regex? you could likely do a simple list comprehension. I mean this is a really cut and dirty way to do it but you could just put
input = "abccbcbbb"
input = list(input)
previous = input.pop(0)
result = [previous]
for letter in input:
if letter != previous : result += letter
previous = letter
result = "".join(result)
and with a method like this, you could make it easier to read and faster with a bit of modification id assume.

Print a string without any other characters except letters, and replace the space with an underscore

I need to print a string, using this rules:
The first letter should be capital and make all other letters are lowercase. Only the characters a-z A-Z are allowed in the name, any other letters have to be deleted(spaces and tabs are not allowed and use underscores are used instead) and string could not be longer then 80 characters.
It seems to me that it is possible to do it somehow like this:
name = "hello2 sjsjs- skskskSkD"
string = name[0].upper() + name[1:].lower()
lenght = len(string) - 1
answer = ""
for letter in string:
x = letter.isalpha()
if x == False:
answer = string.replace(letter,"")
........
return answer
I think it's better to use a for loop or isalpha () here, but I can't think of a better way to do it. Can someone tell me how to do this?
For one-to-one and one-to-None mappings of characters, you can use the .translate() method of strings. The string module provides lists (strings) of the various types of characters including one for all letters in upper and lowercase (string.ascii_letters) but you could also use your own constant string such as 'abcdef....xyzABC...XYZ'.
import string
def cleanLetters(S):
nonLetters = S.translate(str.maketrans('','',' '+string.ascii_letters))
return S.translate(str.maketrans(' ','_',nonLetters))
Output:
cleanLetters("hello2 sjsjs- skskskSkD")
'hello_sjsjs_skskskSkD'
One method to accomplish this is to use regular expressions (regex) via the built-in re library. This enables the capturing of only the valid characters, and ignoring the rest.
Then, using basic string tools for the replacement and capitalisation, then a slice at the end.
For example:
import re
name = 'hello2 sjsjs- skskskSkD'
trans = str.maketrans({' ': '_', '\t': '_'})
''.join(re.findall('[a-zA-Z\s\t]', name)).translate(trans).capitalize()[:80]
>>> 'Hello_sjsjs_skskskskd'
Strings are immutable, so every time you do string.replace() it needs to iterate over the entire string to find characters to replace, and a new string is created. Instead of doing this, you could simply iterate over the current string and create a new list of characters that are valid. When you're done iterating over the string, use str.join() to join them all.
answer_l = []
for letter in string:
if letter == " " or letter == "\t":
answer_l.append("_") # Replace spaces or tabs with _
elif letter.isalpha():
answer_l.append(letter) # Use alphabet characters as-is
# else do nothing
answer = "".join(answer_l)
With string = 'hello2 sjsjs- skskskSkD', we have answer = 'hello_sjsjs_skskskSkD';
Now you could also write this using a generator expression instead of creating the entire list and then joining it. First, we define a function that returns the letter or "_" for our first two conditions, and an empty string for the else condition
def translate(letter):
if letter == " " or letter == "\t":
return "_"
elif letter.isalpha():
return letter
else:
return ""
Then,
answer = "".join(
translate(letter) for letter in string
)
To enforce the 80-character limit, just take answer[:80]. Because of the way slices work in python, this won't throw an error even when the length of answer is less than 80.

Input Name with space with validation

I am using the .isalpha function to take an input of a name. It is working but whenever i put on space between name for example a full name John Doe It gives me error.
What ive Tried so far
while not name.isalpha():
print('Entered Name is invalid')
name = input('Please Enter Your Name Sir: ')
if name.isalpha() or name.isspace():
print('Hello Mr.' + name)
select_mmenu('main-menu.txt')
I've tried combining .isalpha and .isspace but it seems not to be working. Need the most simple way to solve this trick
isalpha tests that each member of the string is a letter. isspace tests that each member of the string is a whitespace character. Neither of those is what you want.
Instead you could do:
if all(lett.isalpha() or lett.isspace() for lett in name):
which will pass if every letter is EITHER a letter or a space. Alternatively you can match a regular expression:
import re # at the top of your module
if re.match(r"[\s\w]+$", name):
which is arguably cleaner, and certainly more powerful. The square brackets denote a character class, \s is all whitespaces and \w is all word character, the + means "matches 1 or more times," and the $ is the end of string. [\s\w]+$ then means "one or more characters that are either whitespace or word characters, and nothing afterwards.
It will certainly give you an error because the method isalpha() checks whether the string consists of alphabetic characters only. So if you put a space, the result will return false instead of true, and you will get an error.
Thankyou for the answers. I got it solved without using all() function. I just solved it with simplest basic Python loops
Thankyou Adam Smith because of your answer i got this idea to solve it through that method
con = False
while con!=True:
l=0
strs = input('Enter your Name: ')
for i in strs:
if i.isalpha() or i.isspace():
l += 1
if l == len(strs):
con = True
break
else:
print('Wrong Input')
if con==True:
print(strs)
In this code its basically counting the input lenght and alphabets and space lenght if it match it works. else the while loop continue.

A check text numbers, alphabets, letters upper case and lower case except symbols

I need guys your help.
I can't understand what to use either list or set. List is more efficient. dictionary also need index. but my problem is text should be string so variable must equal to text as string. I can't D=['a','b','c'].
text gives me error because it can't compare them all except individual and i must create such as abc or word example as _success and confirm its in the list to be true.
This is my code so far but i have problem which is now it accepts numbers and letters and symbols. Symbols such as !##$% should be returning False.
Having it as own function works but i need it in the if statement.
return text.isalnum() doesn't work in the if statement. Thats my problem symbols should be false.
def check(text):
if text== '':
return False
if text.isalpha() == text.isdigit():
return True
else:
return text.isalnum()
def main():
text = str(raw_input("Enter text: "))
print(check(text))
main()
output problem.
Enter text: _
False
_ is suppose to be one of the symbols True. Example _success123 is True
!##$% is suppose to be false but its showing as True as output Another example is !##A123. This output is False.
The code up there does accept the underscore and letter and number
output:
_success123
but problem is also accepts !##$ as True.
return text.isalnum() Does deny the symbols but its not working in the if statement.
It's an overkill, but you can use Regex. It's easy to add new chars (e.g. symbols):
import re
def check(text):
return re.match('^[a-zA-Z0-9_!]*$', text)
text = str(raw_input("Enter text: "))
print(check(text))
If you want to avoid a regular expression, you could use Python sets:
allowed = set('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789')
def check(text):
return not len(set(text) - allowed)
for text in ['_success123', '!##$%']:
print(text, check(text))
This converts your text into a set of characters and removes all the characters that are allowed. If any characters remain then you know it is invalid. For two examples, this gives:
_success123 True
!##$% False

String Format Checking in Python

While preparing for my AS-Level Computer Science exam I came across a question in the pre-release material:
Prompt the user to input a User ID and check if the format of the ID corresponds with pre-defined formatting rules and output accordingly.
The Format (In order):
One upper case letter
Two Lower case letters
Three numeric characters (digits)
Example: "Abc123"
I came up with a solution using my language of choice(Python), however, I was wondering if there is a more elegant or better way to solve this. Especially the third check.
Here is my code:
#Task 2.2
u_id = input("Input User ID: ") #DECLARE u_id : string
numbers = [str(num) for num in range(10)]
#Checking if final 3 characters of User ID (u_id) are digits
for i in list(u_id[3::]):
if i not in numbers:
digit_check = False #DECLARE digit_check : bool
break
else:
digit_check = True
#User ID format check
if (u_id[0:1].isupper() == True) and (u_id[1:3] == u_id[1:3].lower()) and (digit_check == True):
print ("Correct Format")
else:
print ("Wrong Format")
Ignore the DECLARATION comments. They are an exam requirement.
Thanks
If you are allowed to import re:
import re
u_id = input("Input User ID: ") #DECLARE u_id : string
rex = re.compile("^[A-Z][a-z]{2}[0-9]{3}$")
if rex.match(u_id):
print("Correct format")
else:
print("Incorrect")
Explanation of expression:
^ represents the beginning of a string.
[A-Z] is a range, containing all uppercase letters (in the English alphabet).
[a-z] is a range, containing all lowercase letters.
[0-9] is a range, containing all numbers.
{n} specifies that n items (items are whatever is before the curly brackets) will be matched.
$ represents the end of the string.
Also, you can see more detailed explanations and test arbitrary strings against this regular expression here.
If you want to solve it without regular expressions (mind you, in this case they are the right tool!), you could do something like this:
id_format = [
"ABCDEFGHIJKLMNOPQRSTUVWXYZ", # or string.ascii_uppercase etc.
"abcdefghijklmnopqrstuvwxyz",
"abcdefghijklmnopqrstuvwxyz",
"0123456789",
"0123456789",
"0123456789",
]
def check(input):
# check for same length
if len(input) != len(id_format):
return False
for test, valid in zip(input, id_format): # itertools.zip_longest can make
if test not in valid: # the length check unnecessary
return False
return True
check("Abc123") # True
check("abc123") # False

Categories

Resources