I am trying to solve the following problem:
Given a string str, the task is to check if the string is a valid identifier or not. In order to qualify as a valid identifier, the string must satisfy the following conditions:
It must start with either underscore(_) or any of the characters from the ranges [‘a’, ‘z’] and [‘A’, ‘Z’]. There must not be any white space in the string. And, all the subsequent characters after the first character must not consist of any special characters like ,ドル #, % etc.
Examples:
Input: str= "_code123"
Output: Valid
Input: str = "123code_"
Output: Invalid
My attempted solution, which works:
def isValid(str1, n):
# If first character is invalid
if (((ord(str1[0]) >= ord('a') and
ord(str1[0]) <= ord('z')) or
(ord(str1[0]) >= ord('A') and
ord(str1[0]) <= ord('Z')) or
ord(str1[0]) == ord('_')) == False):
return False
# Traverse the string for the rest of the characters
for i in range(1, len(str1)):
if (((ord(str1[i]) >= ord('a') and
ord(str1[i]) <= ord('z')) or
(ord(str1[i]) >= ord('A') and
ord(str1[i]) <= ord('Z')) or
(ord(str1[i]) >= ord('0') and
ord(str1[i]) <= ord('9')) or
ord(str1[i]) == ord('_')) == False):
return False
# is a valid identifier
return True
# Driver code
str1 = "_code123"
n = len(str1)
if (isValid(str1, n)):
print("Valid")
else:
print("Invalid")
How can I make the above code follow OOP principles, without so many nested ifs?
-
1You could use a regular expression.GoodDeeds– GoodDeeds2021年04月25日 23:42:24 +00:00Commented Apr 25, 2021 at 23:42
-
Show some input examples and expected outputDevScheffer– DevScheffer2021年04月25日 23:45:21 +00:00Commented Apr 25, 2021 at 23:45
-
@DevScheffer Check the driver code. It has an examplenerdyGuy– nerdyGuy2021年04月25日 23:50:12 +00:00Commented Apr 25, 2021 at 23:50
-
I mean more than just one example, some valid and invalid casesDevScheffer– DevScheffer2021年04月25日 23:52:23 +00:00Commented Apr 25, 2021 at 23:52
-
@DevScheffer Added the example, but your solution doesnt seem to work if _ is at the end of the expression.nerdyGuy– nerdyGuy2021年04月26日 00:00:11 +00:00Commented Apr 26, 2021 at 0:00
3 Answers 3
Have some read on regex it will help a lot for this kind of problem.
This site is great for practice
import re
def isValid(str1):
res=re.match(r'^[_A-Za-z]\w+$',str1)
return res
str1 = "_code123"
n = len(str1)
if (isValid(str1)):
print("Valid")
else:
print("Invalid")
2 Comments
I think you can use that code.
if re.match('^[a-zA-Z_]+', line) is not None and re.match('^[\w-]+$', line) is not None:
return True
[a-zA-Z_]+ Your string may start with a-z, A-Z and underscore
Comments
There is nothing to say that nested ifs break OOP principles.
On the other hand, Python has certain features to help you out. First, you don't need to use ord so much because comparing two one-character strings does the same thing:
ord('a') < ord('b')
is equivalent to
'a' < 'b'
Second, Python allows you to chain math comparison operators, so instead of
'a' < 'b' and 'b' < 'c''
you can just type
'a' < 'b' < 'c'
But there is still an easier way: using the isalpha and isalphanumeric methods, you can avoid using the comparison operators, converting your code to:
Also, Python allows you to work directly on each character while looping by using the for c in str construct, saving you much indexing.
A more natural implementation of your code would be:
def is_valid(str1, n):
if not (str1[0] == '_' or str1[0].isalpha()):
return False
for c in str1[1:]:
if not (c == '_' or c.isalnum()):
return False
return True
You could even use a list comprehension for the second part, by doing:
if not all(c == '_' or c.isalnum() for c in str1[1:]):
return False