I am trying to implement my own strip method in Python, so without using the built-in method, I'd like my function to strip out all the whitespace from the left and the right.
Here, what I am trying to do is create a list, remove all the blank character before the first non-space character, then do it reverse way, finally return the list to a string. But with what I wrote, it doesn't even remove one whitespace.
I know what I am trying to do might not even work, so I would also like to see the best way to do this. I am really new to programming, so I would take any piece of advise that makes my program better. Thanks!
# main function
inputString = input("Enter here: ")
print(my_strip(inputString))
def my_strip(inputString):
newString = []
for ch in inputString:
newString.append(ch)
print(newString)
i = 0
while i < len(newString):
if i == " ":
del newString[i]
elif i != " ":
return newString
i += 1
print(newString)
Instead of doing a bunch of string operations, let's just get the beginning and ending indices of the non-whitespace portion and return a string slice.
def strip_2(s):
start = 0
end = -1
while s[start].isspace():
start += 1
while s[end].isspace():
end -= 1
end += 1
return s[start:end or None]
How about using regular expression?
import re
def my_strip(s):
return re.sub(r'\s+$', '', re.sub(r'^\s+', '', s))
>>> my_strip(' a c d ')
'a c d'
What you seem to be doing is an ltrim for spaces, since you return from the function when you get a non-space character.
Some changes are needed:
# main function
inputString = input("Enter here: ")
print(my_strip(inputString))
def my_strip(inputString):
newString = []
for ch in inputString:
newString.append(ch)
print(newString)
i = 0
while i < len(newString):
if i == " ": # <== this should be newString[i] == " "
del newString[i]
elif i != " ": # <== this should be newString[i] == " "
return newString
i += 1 # <== this is not needed as the char is deleted, so the next char has the same index
print(newString)
So the updated code will be:
# main function
inputString = input("Enter here: ")
print(my_strip(inputString))
def my_strip(inputString):
newString = []
for ch in inputString:
newString.append(ch)
print(newString)
i = 0
while i < len(newString):
if newString[i] == " ":
del newString[i]
elif newString[i] != " ":
return newString
print(newString)
Good luck with the rest of the exercise (implementation of rtrim).
Related
In the following Python code where I am deciphering a message that should theoretically result in Ready, set go output the two lines with str.replace() are obviously not executing as expected, resulting in only the second character of the word being replaced:
# Input:
# 82yade 115te 103o
#
# Output:
# Ready set go
user_input = input().split(" ")
first_letter = ''
second_letter = ''
last_letter = ''
printable_list = []
ord_char = ''
final_str = ''
concat_str = ''
for word in user_input:
final_str = ''
first_letter = ''
last_letter = ''
ord_char = ''
concat_str = ''
for idx in range(0, len(word)):
if word[idx].isdigit():
first_letter = word[idx]
ord_char += first_letter
else:
final_str += word[idx]
concat_str = chr(int(ord_char)) + final_str
second_letter = concat_str[1]
last_letter = concat_str[len(concat_str) - 1]
print(second_letter, last_letter) # this prints here only for debugging purposes, e.g. to check 2nd and last letter
concat_str = concat_str.replace(last_letter, second_letter)
concat_str = concat_str.replace(second_letter, last_letter)
printable_list.append(concat_str)
print(' '.join(printable_list))
Hence, what I expect to come out as "Ready set go" is "Reade see go". What is causing the second replace to malfunction?
What I tried to achieve is that the second and the last letter are switched (e.g., Holle means Hello) and that the first letter is replaced by its character code (e.g., 72 means H) which runs smoothly until I hit the line replacing the 2nd with my last character of each of the words I add to the printable_list.
Consider the string:
Ryade
If you replace the last_letter (e) with the second_letter (y) you get:
Ryady
Now if you replace second_letter (y) with last_letter (e) you get:
Reade
All of the y's were replaced with e's.
To get around this issue you can introduce a placeholder character (as one of many options):
placeholder = '^'
concat_str = concat_str.replace(last_letter, placeholder)
concat_str = concat_str.replace(second_letter, last_letter)
concat_str = concat_str.replace(placeholder, second_letter)
With this logic our input of Ryade will take the following steps:
Ryed^
Read^
Ready
From my comment below, you may have better success being more tactical about which character you are replacing by using its position in the word (after swapping out that first letter). There are likely prettier ways to do this, but this feels like a reasonable direction:
import re
user_input = input().split(" ")
printable_list = []
for word in user_input:
word = word.replace(re.findall('^[0-9]*', word)[0], chr(int(re.findall('^[0-9]*', word)[0])))
if len(word) > 2:
word = word[0] + word[len(word) - 1] + word[2:len(word)-1] + word[1]
printable_list.append(word)
print(' '.join(printable_list))
str.replace is based on old and new substrings, irrespective of positions.
str.replace(old, new[, count])
Return a copy of the string with all occurrences of substring old replaced by new. If the optional argument count is given, only the first count occurrences are replaced.
You can use f-strings to replace characters at specific positions:
first_letter = concat_str[0]
second_letter = concat_str[1]
third_to_second_last_letter = concat_str[2:-1]
last_letter = concat_str[-1]
# concat_str = concat_str.replace(last_letter, second_letter)
# concat_str = concat_str.replace(second_letter, last_letter)
if len(concat_str) > 2:
concat_str = f'{first_letter}{last_letter}{third_to_second_last_letter}{second_letter}'
A less performant but more obvious swap, using a list of characters since str is immutable:
second_letter = concat_str[1]
last_letter = concat_str[-1]
# concat_str = concat_str.replace(last_letter, second_letter)
# concat_str = concat_str.replace(second_letter, last_letter)
concat_str_list = list(concat_str)
concat_str_list[1], concat_str_list[-1] = last_letter, second_letter
concat_str = ''.join(concat_str_list)
I am revisiting a B-Language translation program example in Python from Stanford's notes. This program works where words are transformed such that every vowel cluster is reduplicated with a leading "b".
For example:
translate("quick") => "quibuick"
translate("spaghetti") => "spabaghebettibi"
The code below works perfectly fine, but due to confusion, I was wondering if there's an alternative way to compute the translate(word, separator="b") function which converts a word string by reduplicating each vowel cluster with a leading b. Is it possible to find out a way which exclude the usage of the computation "start = -1"?
def translate(word, separator="b"):
start = -1
translation = ""
for i in range(len(word)):
ch = word[i]
if isEnglishVowel(ch):
if start == -1:
start = i
else:
if start >= 0:
translation += word[start:i] + separator + word[start:i]
start = -1
translation += ch
if start >= 0:
translation += word[start:] + separator + word[start:]
return translation
def isEnglishVowel(ch):
return len(ch) == 1 and "aeiou".find(ch) >= 0
def TestTranslate():
while True:
word = input("Enter a single word [or hit enter to quit]: ");
if word == "": break
translation = translate(word)
print("\"{}\" -> \"{}\"".format(word, translation))
if __name__ == "__main__":
TestTranslate()
Thank you.
I modified the code a bit. It uses vowels instead of start but the internal logic is a little more simplified. Basically grow vowels until you encounter a consonant, then pop vowels into the translation string with the separator in between.
def translate(word, separator="b"):
translation = ""
vowels = ""
for ch in word:
if vowels and not isEnglishVowel(ch):
translation += separator + vowels
vowels = ""
translation += ch
if isEnglishVowel(ch):
vowels += ch
return translation + separator + vowels if vowels else translation
def isEnglishVowel(ch):
return len(ch) == 1 and ch in 'aeiou'
def TestTranslate():
while True:
word = input("Enter a single word [or hit enter to quit]: ")
if word == "": break
translation = translate(word)
print("\"{}\" -> \"{}\"".format(word, translation))
if __name__ == "__main__":
TestTranslate()
I have to edit the code i previously wrote to make it work with a input, I will attach the problem. I can not seem to get it to work.
it has to be some sort of input,
string =" "
reversed_string = string[::-1]
result_string = " ".join(string)
for a in range (0 ,3):
result_string += chr(ord('a')+a)
for a in range(0 , 2)[::-1]:
result_string += chr(ord('a')+a)
print result_string
string =" "
add this to input from keyboard
input( 'type a letter from a to z')
This is the shortest I could make the answer
character = 97
char_list = []
con = True
a = 0
for interger in range(26):
char = chr(character)
char_list.append(char)
character = character+1
get_char = input("Enter a letter from a-z")
while con == True:
if get_char == char_list[a]:
b = char_list[:a+1]
char_list.reverse()
print(b+char_list[-a:])
con = False
else:
a = a+1
I make a function to input string and return with head and tail with two indexes without space and punctuation. but it's return only "empty string"
def hello(word):
str_cnt = ""
for letter in word:
if letter not in string.whitespace and letter not in string.punctuation:
str_cnt += letter
if len(str_cnt) < 2 :
return "empty string"
else:
return str_cnt[:2] + str_cnt[-2:]
word = input("Input String : ")
result = hello(word)
print("Result: ",result)
I expect when I input "hello world!", and the actual output is "held"
or "Hi!" = "HiHi".
The problem is simply incorrect indentation:
import string
def hello(word):
str_cnt = ""
for letter in word:
if letter not in string.whitespace and letter not in string.punctuation:
str_cnt += letter
if len(str_cnt) < 2:
return "empty string"
return str_cnt[:2] + str_cnt[-2:]
word = input("Input String: ")
result = hello(word)
print("Result: ", result)
Indentation is everything in Python!
> python3 test.py
Input String: hello world!
Result: held
>
However, if the input is long, this is the wrong way to go about the problem. We test a lot of characters we'll never use against the whitespace and punctuation lists. Instead we should grab the first two valid characters from either end of the list and ignore the middle. Something like:
def hello(word):
unwanted = string.whitespace + string.punctuation
str_start = ""
for letter in word:
if letter not in unwanted:
str_start += letter
if len(str_start) == 2:
break
if len(str_start) < 2:
return "empty string"
str_end = ""
for idx in range(len(word) - 1, -1, -1):
if word[idx] not in unwanted:
str_end = word[idx] + str_end
if len(str_end) == 2:
break
return str_start + str_end
EXAMPLE
> python3 test2.py
Input String: telecommunications!
Result: tens
>
The letters 'lecommunicatio' were never tested as they had no effect on the eventual outcome.
You miss-indented the last if block:
import string
def hello(word):
str_cnt = ""
for letter in word:
if letter not in string.whitespace and letter not in string.punctuation:
str_cnt += letter
if len(str_cnt) < 2 :
return "empty string"
else:
return str_cnt[:2] + str_cnt[-2:]
word = input("Input String : ")
result = hello(word)
print("Result: ",result)
Example output:
Input String : Hello World!
Result: Held
Your issue is that you return after the first iteration through the work, no matter what.
Move the return nogic after the logic:
def hello(word):
str_cnt = ""
for letter in word:
if letter not in string.whitespace and letter not in string.punctuation:
str_cnt += letter
if len(str_cnt) < 2 :
return "empty string"
else:
return str_cnt[:2] + str_cnt[-2:]
The problem is indentation as everyone says, after correcting which it works. I would do it more pythonically as:
def hello(word):
w = ''.join([x for x in word if x not in string.whitespace and x not in string.punctuation])
return w[:2] + w[-2:] if len(w) > 1 else 'empty string'
Usage:
>>> hello('hello world!')
held
I'm trying to write a recursive program that returns a string of letters from a word that are non vowels. My code right now print's out all of the non vowels of "University" but never ends . Any ideas?
def removeVowels9(aString):
if len(aString) == 0:
return newString
else:
newString = aString[1:len(aString) + 1]
firstLetter = aString[0]
#print(firstLetter)
if firstLetter in "aeiouAEIOU":
return removeVowels9(newString)
else:
newString = newString + firstLetter
print(newString)
return removeVowels9(newString)
Clearly you are never hitting the base case, because you would get a NameError (newString hasn't been defined).
Why? Let's look at your third case:
else: # starts with consonant
newString = newString + firstLetter # add first letter to the end?
return removeVowels9(newString) # repeat
once you've removed all of the vowels, this just keeps on looping the consonants, as you should have seen from your outputs:
>>> removeVowels9("University")
iversityn
ersitynv
sitynvr
itynvrs
ynvrst # all vowels gone
nvrsty
vrstyn
rstynv
stynvr
tynvrs
ynvrst # just keeps looping
...
Here is the minimal fix:
>>> def removeVowels9(aString):
if len(aString) == 0:
return aString # aString, not newString
else:
newString = aString[1:len(aString) + 1]
firstLetter = aString[0]
#print(firstLetter)
if firstLetter in "aeiouAEIOU":
return removeVowels9(newString)
else:
return firstLetter + removeVowels9(newString) # add first letter back at start, after processing rest
>>> removeVowels9("University")
'nvrsty'
But this could be much neater:
def remove_vowels(s):
"""Recursively remove vowels from the input."""
if not s: # empty string
return s
elif s[0] in "aeiouAEIOU": # first character is vowel
return remove_vowels(s[1:]) # skip first character and process rest
return s[0] + remove_vowels(s[1:]) # return first character and process rest
Which does:
>>> remove_vowels("University")
'nvrsty'
Note compatibility with the style guide for variable names etc..