Please don't give me the answer just point me in the right direction, thank you. Also, I need to do this without isdigit().
I am trying to create a program that checks all the characters of a string and if any of them are not natural numbers then the program will return False otherwise it will return True.
This is what i have so far:
numbers = ["0123456789"]
if len(str) > 0:
for i in str:
if i not in numbers:
return False
else:
return True
I have a few test cases and the problem I'm having is that when I return, the whole program just ends. I need to find a way to include the else: return True
You would need to remove the numbers from the list as you are comparing each character to all the digits at once i.e "1" == "0123456789" , you also need to check every char before returning True:
def is_dig(s):
numbers = "0123456789" # single iterable of the numbers
for i in s:
if i not in numbers:
return False
return bool(s) # return outside the loop also catching empty string
A more efficient approach would be to use the ord and all:
def is_dig(s):
return len(s) > 0 and all(48 <= ord(ch) <= 57 for ch in s)
The ord of "0" is 48 and the ord of "9" is 57 so if the ord of the char falls in that range then you have a digit, if not all will short circuit and return False.
Using the ord without all and following your own logic would look something like:
def is_dig(s):
if not s: # empty string
return False
for ch in s:
if not 48 <= ord(ch) <= 57:
return False
return True
numbers = "0123456789"
if len(str) > 0:
for i in str:
if i not in numbers:
return False
return True
Thanks Padraic and everyone for the input. #Till Hoffmann your answer was exactly what i was looking for
Related
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?
Have some read on regex it will help a lot for this kind of problem.
https://regexr.com/
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")
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
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
My python function is supposed to take an input that is a string (of only letters and only lowercase letters). The function should output true if there are no repeating letters ( regardless of whether they are consecutive letters or not) and it's suppose to return false if there are repeating letters. My code only checks if the first letter is repeating or not, but doesn't check any other letter in the string. What is the issue?
Try this
def is_isogram(string):
for x in string:
if string.count(x) > 1:
return False
return True
You want to return True only if you pass through all the for loop
the following should rectify.
def is_isogram(s: str):
# loop through all unique chars
for x in set(s):
if s.count(x) > 1:
return True
# terminate after looping through all chars
return False
additionally convert string to a set to eliminate iterating over same char twice.
You're not making it past the first character because in the first iteration of the for loop, your "else" exits the function if the if statement returns false.
My solution
def is_isogram(x):
if len(str(x)) > len(set(x)):
return False
else:
return True
Write a function repfree(s) that takes as input a string s and checks whether any character appears more than once. The function should return True if there are no repetitions and False otherwise.
I have tried this but I don't feel this is an efficient way of solving it. Can you suggest an efficient code for this, thanks?
def repfree(s):
newlist = []
for i in range(0, len(s)):
newlist.append(s[i])
newlist2 = set(newlist)
if len(newlist) == len(newlist2):
print("True")
else:
print("False")
One easy way to meet this requirement is to use regular expressions. You may not be allowed to use them, but if you can, then consider this:
def repfree(s):
if re.search(r'^.*(.).*\1.*$', s):
print("True")
else:
print("False")
Believe it or not, this problem can be solved in O(1) time, because every sufficiently large string contains at least one duplicate character. There are only a finite number of different Unicode characters, after all, so a string cannot be arbitrarily long while also using each Unicode character at most once.
For example, if you happen to know that your strings are formed of only lowercase letters, you can do this:
def has_repeated_char(s):
return len(s) > 26 or len(s) != len(set(s))
Otherwise you can replace the 26 with whatever number of characters your string could possibly contain; e.g. 62 for upper- and lowercase letters and digits.
As of February 2020, the whole of Unicode has 137,994 distinct characters (Wikipedia), so if your string length is 150,000 then you can return True without searching.
Try
chars = 'abcdefghijklmnopqrstuvwxyz'
def repfree(s):
for char in chars:
count = s.count(char)
if count > 1:
return False
return True
But, this is a long way as it scans the list 26 times. A much better and Pythonic way would be
import collections
def repfree(s):
results = collections.Counter(s)
for i in results:
if results[i] > 1:
return False
return True
Here, results is a dictionary that contains all the characters of s as key, and their respective frequency as value. Further, it is checked if any value is greater than 1, repetition has occurred.
You could split the string characters to a set and compare the length
def repfree(s):
se = set(string)
print(len(se) == len(s))
You can make your approach more efficient by removing the for loop.
len(s) == len(set(s))
Otherwise, try using any
any(s.count(c) > 1 for c in s)
You could do this way:
Method 1:
def repfree(s):
if len(set(s)) == len(s):
return True
return False
Method 2:
def repfree(s):
return len(set(s)) == len(s)
Why set?
set will return the list of all unique characters in the string in sorted order
Example :
set('shubham')
Output:
{'a', 'b', 'h', 'm', 's', 'u'}
So,if a character in a string appears more than once,it will not be equal to the length of string itself.
def repfree(str):
l=list(str)
for i in range(len(l)):
check=str.count(l[i])
if check>1:
flag=1
else:
flag=0
if(flag==1):
return False
else:
return True
def matched(s):
stack = []
for char in s:
if char == '(':
stack.append(char)
elif char == ')':
if not stack:
return False
stack.pop()
return not stack
I'm having trouble with creating a function that takes an argument of a string and returns just the numbers in type str. My code looks something like this.:
def check_if_number(number_string):
for ch in number_string:
if ch.isdigit():
num = number_string[ch]
return num
print(check_if_number('1655t'), end='')
It should print: 1655
You should add each char to a string if it is a digit :
def check_if_number(number_string):
digit_string = ""
for ch in number_string:
if ch.isdigit():
digit_string += ch
return digit_string
print(check_if_number('1655t'))
# 1655
Note that you can also use the re library :
import re
re.sub("\D", "", "1655t")
#1655
This code replace every non-digit character (matched by \D) by an empty string.
Have a look at this question to find more way to do it
You can do this :
def check_if_number(number_string):
num = ""
for ix in number_string :
if ix.isdigit():
num += ix
return int(num)
This function will return 1655, if the input is 1655t. You return from the function once you scan the complete string and append all ints to a string.
The easy way would be just using filter and concatenating the filtered letters in the end:
def check_if_number(number_string):
return ''.join(filter(str.isdigit, number_string))
Assuming all numbers are together (i.e. No letters exist between digits like "1e234g7"),
def check_if_number(number_string):
num = ''
for ch in number_string:
if ch.isdigit():
num += ch
return num
print(check_if_number('1655t'), end='')
This will return a string that only has digits in it. If you want to return a type int, then simply do return int(num).
If you want to take floats into account as well:
def check_if_number(number_string):
num = ''
for ch in number_string:
if ch == '.' or ch.isdigit():
num += ch
return num
print(check_if_number('1655t'), end='')
Similarly, this will return a string. If you want type float, simply do return float(num).
I tried not to deviate too much from what you already had... I hope this helps.
I'm uncertain what check_leap_year() function is so I just commented it out and called the function you gave us instead.
When you pass anything into a function in order to manipulate it and spit it back out different than it came in you should create a new variable for the changed data set.
In this case I used num = ""
By initiating an empty string inside of the function I can now add the data that pass my condition to that new, empty string.
isdigit() returns a boolean. So instead of using if x.isdigit: get in the habit of checking the boolean. Try if x.isdigit() is True instead.
Return your finished new string AFTER it is finished. Make sure your return statement is indented correctly or you are only going to return one number instead of all of them. The return should be outside of the loop so that it will only return once the loop is done.
num_string = "1a2s3d4f5g666hhh777jjj888kkk9l0"
def check_if_number(number_string):
num = ""
for ch in number_string:
if ch.isdigit() is True:
num += ch
return num
print(check_if_number(num_string))
Output:
>>> 1234566677788890
An isogram is a word that has no repeating letters, consecutive or non-consecutive. Implement a function that determines whether a string that contains only letters is an isogram. Assume the empty string is an isogram. Ignore letter case.
is_isogram("Dermatoglyphics" ) == true
is_isogram("aba" ) == false
is_isogram("moOse" ) == false # -- ignore letter case
Here is my code:
def is_isogram(string):
string = string.lower()
for char in string:
if string.count(char) > 1:
return False
else:
return True
And when I tried to run the test code Test.assert_equals(is_isogram("moOse"), False, "same chars may not be same case" ) It failed, but I thought I did convert everything into lowercase. Can someone help?
Try this:
def is_isogram(string):
string = string.lower()
for char in string:
if string.count(char) > 1:
return False
return True
In your code when is_isogram("moose") is called, it will see that the first character's ('m') count is not greater than 1. So it will return True. Once it hits the return statement, it will stop the execution for the rest string. So you should really write return True only after for-loop to make sure that the function checks for the whole string.
If however, at any point, it finds a character's count to be greater than 1, then it will simply return False and stop executing because there's no point of checking any more when one point is found where condition does not hold.
How about using sets? Casting the string into a set will drop the duplicate characters, causing isograms to return as True, as the length of the set won't differ from the length of the original string:
def is_isogram(s):
s = s.lower()
return len(set(s)) == len(s)
print is_isogram("Dermatoglyphics")
print is_isogram("aba")
print is_isogram("moOse")
print is_isogram("")
This outputs:
True
False
False
True
Try this :
def is_isogram(s):
string = s.lower()
if len(s) == len(set(string)):
return True
return False
Try this out:
def is_isogram(string):
return len(string) == len(set(string.lower()))
"Implement a function that determines whether a string that contains only letters is an isogram."
By using sets, you can create unique elements. So if there are any repeating numbers, it will only select one. By calling len() on these strings, you can compare the length to the original.
Sorry if I explained it poorly. I am working on this.
let us define an isogram well:
according to wikipedia An Isogram is a word in which no letter occurs more than once.
check here for more about an isogram
just remind letter
I write this code and it works for me :
def is_isogram(argument):
print(len(argument))
if isinstance(argument,str):
valeur=argument.lower()
if not argument:
return False
else:
for char in valeur:
if valeur.count(char)>1 or not char.isalpha():
return False
return True
else:
raise TypeError("need a string ")
NB: the hidden test is the fact that you must check if the char in the string is a alpha character a-z, when i add this it pass all the hiddens tests
up vote if this help
I reckon this might not be the best solution in terms of maximizing memory space and time. This answer is just for intuition purposes using a dictionary and two for loops:
def is_isogram(string):
#your code here
#create an empty dictionary
m={}
#loop through the string and check for repeating characters
for char in string:
#make all characters lower case to ignore case variations
char = char.lower()
if char in m:
m[char] += 1
else:
m[char] = 1
#loop through dictionary and get value counts.
for j, v in m.items():
#if there is a letter/character with a count > 1 return False
if v > 1:
return False
#Notice the scope of the "return True" command. It is outside.
return True