I am currently writing a JES program that returns True or False dependent on whether a string containing a palindrome is passed to it. Although the program works, it fails when a capital letter or punctuation symbol is present. How could I get it to work?
print(ThisPalindrome("racecar"))
>> True
print(ThisPalindrome("Racecar"))
>> False
To solve the issue with capitalization, you could try using the str.lower() method in your checks.
def ThisPalindrome(word):
lowercase = word.lower()
reversedOrder = reversed(lowercase)
if lowercase == ''.join(reversedOrder):
return True
else:
return False
In theory, this function should work with basic punctuation too, as long as it doesn't break the function. Input such as ' could cause it to break.
The toLowerCase() method to return the calling string value converted to lowercase.
The replace() method to return a new string with some or all matches of a pattern replaced by a replacement. We will use one of the RegExp we just created earlier.
The split() method splits a String object into an array of strings by separating the string into sub strings.
The reverse() method reverses an array in place. The first array element becomes the last and the last becomes the first.
Related
I am trying to change the first letter of the string so that it is upper case. I know it is posible to use capitalize() or title() but I am just testing things out and wanted to know how I could do the same thing with upper(). The code I've tried comes up with error message: 'TypeError: newS must be a string on line 10'. Any suggestions would be very much appreciated!
def uppercase(string):
string = string.replace(string[0],string[0].upper)
return string
print uppercase("hello")
You missed () while calling upper which is a method:
def uppercase(string):
string = string.replace(string[0],string[0].upper(), 1)
return string
print(uppercase("hello"))
Also, as deceze pointed the replace() based approach will fail as is and you can use the optional maxreplace parameter to 1 to only replace the first occurrence.
You might do
def uppercase(string):
string = string.replace(string[0],string[0].upper(),1)
return string
print uppercase("hello")
Note that there is .upper() i.e. method is called and 1 limit number of replacements, so aaa would became Aaa rather than AAA. This solution assumes string will never be empty str.
I have a regular expression that eliminates all non-alpha characters
def genLetters(string):
regex = re.compile('[^a-zA-Z]')
newString = regex.sub("", string)
If I want to make this string lowercase, I have to define a new string (since they are immutable) like
lowerString = newString.lower()
It seems dumb to me that I would have to make a second string just to do the to lower, but if I remove the A-Z from the regex, I lose any characters that are uppercase which I don't want. I just want a final product of everything lower case.
Can this be done without the lowerString, or even cooler, can it be done in one line?
newString = regex.sub("", string).lower()
Try to think of "functions returning" as "replacing the function call with the return value of the function". For example in the above case, regex.sub is evaluated first, and you should imagine that that call is replaced by the return value:
newString = "some String after substitution".lower()
This means that you can do everything you can do to a string on the return value of regex.sub. You can also call methods on the return value of lower().
This also means that you can do your whole function in one line!
newString = re.compile('[^a-zA-Z]').sub("", string).lower()
Although this might be less readable.
By the way, the standard naming convention in python is not camel case but with underscores, so newString should be new_string.
To do:
Convert python to ythonpay (i.e. pick up a first letter, put it in the end and add 'ay' and make sure the user has not entered in the word numbers or alphanumeric word )
def check(word):
if word.isalnum() or word.isdigit():
print ("Enter valid word!")
else:
print ("Thank You for Entering a valid word!")
first_letter = word[0]
new_word = word.strip(word[0])
PygLatin = new_word+first_letter+"ay"
print (PygLatin)
word= input("enter a word:").lower()
result = check(word)
result I got:
1>> enter a word -> python
2>> Enter valid word!
There are two fundamental issues with your code (and one stylistic issue).
Usually you want functions to return something. For example your intention is to take a word, move the first letter to the end of the word, and add "ay" ... in other words to render it in "Pig Latin."
But you're print-ing the results rather than return-ing them. You might think that using print returns a value (in the sense that it "returned" something to your screen or terminal). But that's not what "return" means in computer programming. The Python return statement is how your function returns a result to the rest of the program following any particular invocation of (or "call into") your function.
Here's the simplest function that would work:
def pigify(word):
return word[1:]+word[0].lower()+'ay'
... that will take a "slice" of the word from a one character offset into the string all the way to the end of the string. That's what [1:] means ... it describes a range of characters, how far to the start of the range and then how far to go to get up to (but not including) the end. Then it adds the first character (which is "zero characters" from the beginning of the string), converts that to lower case (which is harmless for all characters, and only affects capital letters) and then it adds the literal string "ay" ... and it takes all of that and returns it.
pig_latin = pigify("Python")
print(pig_latin)
# ---> prints "ythonpay"
The other issue with your code is that you're calling string methods in a confused way. word.alnum() will return True only if all the characters are alphanumeric and word.isdigit() will return True only if all of the characters are numeric. That's the same as just calling word.isdigit() since digits are a proper subset of the alphanumeric character set. In other words the only strings that will pass your code will be those which contain no letters (or other characters); clearly not what you intended.
You probably would prefer to check that the string consists entirely of alphabetic characters:
def pigify(word):
if word.isalpha():
return word[1:]+word[0].lower()+'ay'
# or else? ....
This leaves you with the question of what you should do with an invalid argument (value passed to your function's "word" parameter by the caller).
You could print an error message. But that's considered poor programming practice. You could return some special value such as Python's None value; but then code that calls your function must either check the results every time, or results can cause some other error far removed from where your function was called (where this non-string value was returned).
You can also raise an exception:
def pigify(word):
if word.isalpha():
return word[1:]+word[0].lower()+'ay'
raise ValueError("Invalid input for pigify()")
... note that I don't need to explicitly spell out else in this case; the control flow only reaches that statement if I didn't return a value, only when it's an error. Any other time the control flow returns to the calling code (the part of the program that called my pigify() function).
Another thing I could do is decide that pigify() simply returns anything that doesn't look like a "word" exactly as it was passed:
def pigify(word):
if word.isalpha():
return word[1:]+word[0].lower()+'ay'
else:
return word
... here I could just return word without the else: as it did before with the raise statement. But I personally think that looks wrong; so I've explicitly spelled out the else: clause purely for stylistic reasons.
Mostly you want your program to be composed of functions (or objects with methods) that work with (manipulate) the data, and then a smaller body of code (possibly functions or object and their methods) which then "render" the results of those manipulations. Any time you're writing a function which manipulations or transforms data and writes those results to the screen or into a web page, or out to a file or database, you should pause and reconsider your design. The transformative/manipulations and computations might be re-useable while the code which writes results is typically quite specific. So interleaving one with the other is usually a bad decision.
The str.isdigit() and str.isalnum() methods only return true if all of the characters match the criteria. Your test is written so that you want to detect whether any of the characters match the criteria:
>>> word = 'abc123'
>>> word.isdigit()
False
>>> any(map(str.isdigit, word))
True
So you can amend the code to start with something like this:
def check(word):
if not word.isalnum() or any(map(str.isdigit, word)):
print ("Enter valid word!")
else:
print ("Thank You for Entering a valid word!")
...
FWIW, str.isalpha() would be easier to use because digits are already excluded.
In your code, you have problem with isalnum() which returns true if string contains only alphabets, only numbers or contains both alphabets and numbers so you can try to match if string only contains alphabets and execute your code as follow:
def check(word):
if word.isalpha(): # process only if word contains only alphabets
print("Thank You for Entering a valid word : {}!".format(word))
print(word[1:] + word[0] + "ay") # slicing is better choice in your case
else:
print("Enter valid word!!!")
word = input("enter a word:")
result = check(word.lower())
This question already has answers here:
How can I invert (swap) the case of each letter in a string?
(8 answers)
Closed 7 years ago.
I'm rank new in Python, thus the question,
I'm trying to solve a simple problem, where the program takes in a simple string and swaps all the cases. Thus if we enter
SimPLE
We should get
sIMple
This is my code
def main():
oldStr = input()
for s in oldStr:
if s.islower():
s.upper()
elif s.isupper():
s.lower()
print(oldStr)
if __name__ == "__main__" : main()
It just returns the same string. Any help appreciated.
As a generator expression:
mystr = "SimPLE"
print("".join(c.upper() if c.islower() else c.lower() for c in mystr))
The breakdown of the above is:
c.upper() if c.islower() else c.lower()
is an conditional expression that will convert a character from upper to lower case and vice versa.
Then,
(... for c in mystr)
is a generator expression, which is somewhat like a list that is generated on-the-fly.
Finally:
".join(...)
will join any sequence of strings together with nothing ("") between them.
Do this in one fell swoop with a string join on a list comprehension of individual characters:
outstr = ''.join([s.upper() if s.islower() else s.lower() for s in oldStr])
print(outstr)
Input & Output:
sIMple
SimPLE
Strings are immutable. What this means is that when you use the function s.upper(), it is not setting that letter in str to be uppercase, it simply returns that letter in uppercase.
Here is some code that works:
def main():
oldStr = input()
newStr = ""
for s in oldStr:
if s.islower():
newStr+=s.upper()
elif s.isupper():
newStr+=s.lower()
print(newStr)
Notice now that we are creating a new string and simply adding the letters at each point in the forloop as opposed to changing those letters in str.
You are running each character through lower() and upper(), but these functions do not change the character.
Instead, they return the modified version of the character. The original character s will stay as it is.
You should build a new string based off the return values of lower() and upper(), and return that string.
1) you need to put the main() call on new line, as python relies on whitespace heavily for program structure
2) s is a temporary variable created for the purpose of the for statement. It doesn't actually reference the character in the string
Essentially what is going on is that s has the same value as the character in the string, but it IS NOT ACTUALLY the character in the string.
This is a homework question. I need to define a function that takes a word and letter and deletes all occurrences of that letter in the word. I can't use stuff like regex or the string library. I've tried...
def delete(word,letter):
word = []
char = ""
if char != letter:
word+=char
return word
and
def delete(word,letter):
word = []
char = ""
if char != letter: #I also tried "if char not letter" for both
word = word.append(char)
return word
Both don't give any output. What am I doing wrong?
Well, look at your functions closely:
def delete(word,letter):
word = []
char = ""
if char != letter:
word+=char # or `word = word.append(char)` in 2nd version
return word
So, the function gets a word and a letter passed in. The first thing you do is throw away the word, because you are overwriting the local variable with a different value (a new empty list). Next, you are initializing an empty string char and compare its content (it’s empty) with the passed letter. If they are not equal, i.e. if letter is not an empty string, the empty string in char is added to the (empty list) word. And then word is returned.
Also note that you cannot add a string to a list. The + operation on lists is only implemented to combine two lists, so your append version is definitelly less wrong. Given that you want a string as a result, it makes more sense to just store the result as one to begin with.
Instead of adding an empty string to an empty string/list when something completely unrelated to the passed word happens, what you rather want to do is keep the original word intact and somehow look at each character. You basically want to loop through the word and keep all characters that are not the passed letter; something like this:
def delete(word, letter):
newWord = '' # let's not overwrite the passed word
for char in word:
# `char` is now each character of the original word.
# Here you now need to decide if you want to keep the
# character for `newWord` or not.
return newWord
The for var in something will basically take the sequence something and execute the loop body for each value of that sequence, identified using the variable var. Strings are sequences of characters, so the loop variable will contain a single character and the loop body is executed for each character within the string.
You're not doing anything with word passed to your function. Ultimately, you need to iterate over the word passed into your function (for character in word: doSomething_with_character) and build your output from that.
def delete(word, ch):
return filter(lambda c: c != ch, word)
Basically, just a linear pass over the string, dropping out letters that match ch.
filter takes a higher order function and an iterable. A string is an iterable and iterating over it iterates over the characters it contains. filter removes the elements from the iterable for which the higher order function returns False.
In this case, we filter out all characters that are equal to the passed ch argument.
I like the functional style #TC1 and #user2041448 that is worth understanding. Here's another implementation:
def delete( letter, string ):
s2 = []
for c in string:
if c!=letter:
s2.append( c )
return ''.join(s2)
Your first function uses + operator with a list which probably isn't the most appropriate choice. The + operator should probably be reserved for strings (and use .append() function with lists).
If the intent is to return a string, assign "" instead of [], and use + operators.
If the intent is to return a list of characters assign [], and use .append() function.
Change the name of the variable you are using to construct the returned value.
Assigning anything to word gets rid of the content that was given to the function as an argument.
so make it result=[] OR result="" etc..
ALSO:
the way you seem to be attempting to solve this requires you to loop over the characters in the original string, the code you posted does not loop at all.
you could use a for loop with this type of semantic:
for characterVar in stringVar:
controlled-code-here
code-after-loop
you can/should change the names of course, but i named them in a way that should help you understand. In your case stringVar would be replaced with word and you would append or add characterVar to result if it isn't the deleted character. Any code that you wish to be contained in the loop must be indented. the first unindented line following the control line indicates to python that the code comes AFTER the loop.
This is what I came up with:
def delete(word, letter):
new_word = ""
for i in word:
if i != letter:
new_word += i
return new_word