Python 3 - Check letters in string with the next letter - python

If I have a string
String = 'ABCEEFGH'
How can I check what letter is beside each letter without going out of index?
for index in range(len(String)):
if String[index] == String[index+1]:
print('Double')

You can use enumerate, slicing the string up to the second last character:
String = 'ABCEEFGH'
for ind,ch in enumerate(String[:-1]):
if ch == String[ind+1]:
print('Double')
In your own code the logic would be the same len(String)-1 but enumerate is the way to go:
for index in range(len(String)-1):
if String[index] == String[index+1]:
print('Double')
The fact you seen to only want to check if any two adjacent characters are identical, maybe using any would be best:
String = 'ABCEEFGH'
if any( ch == String[ind+1] for ind, ch in enumerate(String[:-1])):
print('Double',ch)
any will short circuit and break the loop as soon the condition is Trueor else evaluate to False if we have no match.

>>> text = 'ABCEEFGH'
>>> for c1, c2 in zip(text, text[1:]):
if c1 == c2:
print 'double'
double

These kinds of problems are almost always easier if you think of comparing with the previous letter instead of the next one. It's a lot easier to remember letters you've already seen than to look ahead.
text = 'ABCEEFGH'
prev = ''
for letter in text:
if letter == prev:
print("letter duplicated:", letter)
prev = letter

You can use regular expressions:
for match in re.findall(r'([a-z])\1', your_string):
print('Double letters found here.')

Related

How to remove first occurrence of a letter?

I know how to remove the first occurrence of a letter using splicing, but I'm trying to achieve this without using any of the string functions like splicing, .find(), .count(), etc. I can't seem to figure out how you complete it without splicing.
Here's what I currently have with splicing that works correctly:
s1 = ''
s2 = len(remWord)
for i in range(s2):
if (remWord[i] == remLetter):
s1 = remWord[0:i] + remWord[i + 1:s2]
return s1
Any assistance would be great.
I am assuming that you do not remove anything if the letter is not contained in the string, so you can use the following code:
Strictly not using splicing
new_string = ''
found = False
for i in range(len(remWord)):
if remWord[i] != remLetter or found:
new_string += remWord[i]
else:
found = True
If you are allowed to use splicing
new_string = ''
for i in range(len(remWord)):
if remWord[i] != remLetter:
new_string += remWord[i]
else:
break
new_string += remWord[i + 1:]
You should stop the processing as soon as you encounter the first letter, use a break for this purpose.
remWord = 'this is the word to process'
remLetter = 's'
s1 = ''
s2 = len(remWord)
for i in range(s2):
if (remWord[i] == remLetter):
s1 = remWord[0:i] + remWord[i + 1:s2]
break
print s1
output:
$ python firstletter.py
thi is the word to process
If you omit the break, your output will be like this
$ python firstletter.py
this is the word to proces
As the if clause will be satisfied for the last encounter of the remLetter present in your input string
Strings are sequence types, so we can do this (mostly) with just sequence operations.
seen = False
chars = ''
for ch in remWord:
if ch == remLetter and not seen:
seen = True
else:
chars += ch
The trouble with this is it’s a little expensive because you’re creating a new string each time. Alternatively you can make chars a list and use StringIO, or ''.join if you can get away with it.

Cannot remove two vowels in a row

I have to enter a string, remove all spaces and print the string without vowels. I also have to print a string of all the removed vowels.
I have gotten very close to this goal, but for some reason when I try to remove all the vowels it will not remove two vowels in a row. Why is this? Please give answers for this specific block of code, as solutions have helped me solve the challenge but not my specific problem
# first define our function
def disemvowel(words):
# separate the sentence into separate letters in a list
no_v = list(words.lower().replace(" ", ""))
print no_v
# create an empty list for all vowels
v = []
# assign the number 0 to a
a = 0
for l in no_v:
# if a letter in the list is a vowel:
if l == "a" or l == "e" or l == "i" or l == "o" or l == "u":
# add it to the vowel list
v.append(l)
#print v
# delete it from the original list with a
del no_v[a]
print no_v
# increment a by 1, in order to keep a's position in the list moving
else:
a += 1
# print both lists with all spaces removed, joined together
print "".join(no_v)
print "".join(v)
disemvowel(raw_input(""))
Mistakes
So there are a lot of other, and perhaps better approaches to solve this problem. But as you mentioned I just discuss your failures or what you can do better.
1. Make a list of input word
There are a lot of thins you could do better
no_v = list(words.lower().replace(" ", ""))
You don't replaces all spaces cause of " " -> " " so just use this instead
no_v = list(words.lower().translate( None, string.whitespace))
2. Replace for loop with while loop
Because if you delete an element of the list the for l in no_v: will go to the next position. But because of the deletion you need the same position, to remove all the vowels in no_v and put them in v.
while a < len(no_v):
l = no_v[a]
3. Return the values
Cause it's a function don't print the values just return them. In this case replace the print no_v print v and just return and print them.
return (no_v,v) # returning both lists as tuple
4. Not a mistake but be prepared for python 3.x
Just try to use always print("Have a nice day") instead of print "Have a nice day"
Your Algorithm without the mistakes
Your algorithm now looks like this
import string
def disemvowel(words):
no_v = list(words.lower().translate( None, string.whitespace))
v = []
a = 0
while a < len(no_v):
l = no_v[a]
if l == "a" or l == "e" or l == "i" or l == "o" or l == "u":
v.append(l)
del no_v[a]
else:
a += 1
return ("".join(no_v),"".join(v))
print(disemvowel("Stackoverflow is cool !"))
Output
For the sentence Stackoverflow is cool !\n it outputs
('stckvrflwscl!', 'aoeoioo')
How I would do this in python
Not asked but I give you a solution I would probably use. Cause it has something to do with string replacement, or matching I would just use regex.
def myDisemvowel(words):
words = words.lower().translate( None, string.whitespace)
nv = re.sub("[aeiou]*","", words)
v = re.sub("[^a^e^i^o^u]*","", words)
return (nv, v)
print(myDisemvowel("Stackoverflow is cool !\n"))
I use just a regular expression and for the nv string I just replace all voewls with and empty string. For the vowel string I just replace the group of all non vowels with an empty string. If you write this compact, you could solve this with 2 lines of code (Just returning the replacement)
Output
For the sentence Stackoverflow is cool !\n it outputs
('stckvrflwscl!', 'aoeoioo')
You are modifying no_v while iterating through it. It'd be a lot simpler just to make two new lists, one with vowels and one without.
Another option is to convert it to a while loop:
while a < len(no_v):
l = no_v[a]
This way you have just a single variable tracking your place in no_v instead of the two you currently have.
For educational purposes, this all can be made significantly less cumbersome.
def devowel(input_str, vowels="aeiou"):
filtered_chars = [char for char in input_str
if char.lower() not in vowels and not char.isspace()]
return ''.join(filtered_chars)
assert devowel('big BOOM') == 'bgBM'
To help you learn, do the following:
Define a function that returns True if a particular character has to be removed.
Using that function, loop through the characters of the input string and only leave eligible characters.
In the above, avoid using indexes and len(), instead iterate over characters, as in for char in input_str:.
Learn about list comprehensions.
(Bonus points:) Read about the filter function.

Python empty string index error

How do I stop the index error that occurs whenever I input an empty string?
s = input("Enter a phrase: ")
if s[0] in ["a","e","i","o","u","A","E","I","O","U"]:
print("an", s)
else:
print("a", s)
You can use the str.startswith() method to test if a string starts with a specific character; the method takes either a single string, or a tuple of strings:
if s.lower().startswith(tuple('aeiou')):
The str.startswith() method doesn't care if s is empty:
>>> s = ''
>>> s.startswith('a')
False
By using str.lower() you can save yourself from having to type out all vowels in both lower and upper case; you can just store vowels into a separate variable to reuse the same tuple everywhere you need it:
vowels = tuple('aeiou')
if s.lower().startswith(vowels):
In that case I'd just include the uppercase characters; you only need to type it out once, after all:
vowels = tuple('aeiouAEIOU')
if s.startswith(vowels):
This will check the boolean value of s first, and only if it's True it will try to get the first character. Since a empty string is boolean False it will never go there unless you have at least a one-character string.
if s and s[0] in ["a","e","i","o","u","A","E","I","O","U"]:
print("an", s)
General solution using try/except:
s = input("Enter a phrase: ")
try:
if s[0].lower() in "aeiou":
print("an", s)
else:
print("a", s)
except IndexError:
# stuff you want to do if string is empty
Another approach:
s = ""
while len(s) == 0:
s = input("Enter a phrase: ")
if s[0].lower() in "aeiou":
print("an", s)
else:
print("a", s)
Even shorter:if s[0:][0] in vowels: but of course this not pass as 'pythonic' I guess. What it does: a slice (variable[from:to]) may be empty without causing an error. We just have to make sure that only the first element is returned in case the input is longer than 1 character.
Edit: no, sorry, this will not work if s=''. You have to use 'if s[0:][0:] in vowels:' but this clearly crosses a line now. Ugly.
Just use
if s:
if s[0] in vowels:
as suggested before.

Return Boolean depending on whether or not string is in alphabetical order

This is what I have so far in python:
def Alphaword():
alphabet = "abcdefghijklmnopqrstuvwxyz"
x = alphabet.split()
i = 0
word = input("Enter a word: ").split()
I'm planning on using a for loop for this problem but not sure how to start it.
Think about it this way - a word containing letters (if they're in alphabetical order) should be equal to itself when forced to be in alphabetical order, so:
def alpha_word():
word = list(input('Enter a word: '))
return word == sorted(word)
That's the naive approach anyway... if you had massive iterables of sequences, there are other techniques, but for strings typed via input, it's practical enough.
There are two ways:
You just loop over each char in the string, use a test like if a[i]<a[i+1]. This works because 'a' < 'b' is true.
You can split string to char list, sort it and compare it to the original list.
Python supports direct comparison of characters. For instance, 'a' < 'b' < 'c' and so on. Use a for loop to go through each letter in the word and compare it to the previous letter:
def is_alphabetical(word):
lowest = word[0]
for letter in word:
if letter >= lowest:
lowest = letter
else:
return False
return True

Small issue with Palindrome program

I've been working on this Palindrome program and am really close to completing it.Close to the point that it's driving me a bit crazy haha.
The program is supposed to check each 'phrase' to determine if it is a Palindrome or not and return a lowercase version with white space and punctuation removed if it is in fact a Palindrome. Otherwise, if not, it's supposed to return None.
I'm just having an issue with bringing my test data into the function. I can't seem to think of the correct way of dealing with it. It's probably pretty simple...Any ideas?
Thanks!
import string
def reverse(word):
newword = ''
letterflag = -1
for numoletter in word:
newword += word[letterflag]
letterflag -= 1
return newword
def Palindromize(phrase):
for punct in string.punctuation:
phrase= phrase.replace(punct,'')
phrase = str(phrase.lower())
firstindex = 0
secondindex = len(phrase) - 1
flag = 0
while firstindex != secondindex and firstindex < secondindex:
char1 = phrase[firstindex]
char2 = phrase[secondindex]
if char1 == char2:
flag += 1
else:
break
firstindex += 1
secondindex -= 1
if flag == len(phrase) // (2):
print phrase.strip()
else:
print None
def Main():
data = ['Murder for a jar of red rum',12321, 'nope', 'abcbA', 3443, 'what',
'Never odd or even', 'Rats live on no evil star']
for word in data:
word == word.split()
Palindromize(word)
if __name__ == '__main__':
Main()
Maybe this line is causing the problems.
for word in data:
word == word.split() # This line.
Palindromize(word)
You're testing for equality here, rather than reassigning the variable word which can be done using word = word.split(). word then becomes a list, and you might want to iterate over the list using
for elem in word:
Palindromize(elem)
Also, you seem to be calling the split method on int, which is not possible, try converting them to strings.
Also, why do you convert the phrase to lower case in the for loop, just doing it once will suffice.
At the "core" of your program, you could do much better in Python, using filter for example. Here is a quick demonstration:
>>> phrase = 'Murder for a jar of red rum!'
>>> normalized = filter(str.isalnum, phrase.lower())
>>> normalized
'murderforajarofredrum'
>>> reversed = normalized[-1::-1]
>>> reversed
'murderforajarofredrum'
# Test is it is a palindrome
>>> reversed == normalized
True
Before you go bananas, let's rethink the problem:
You have already pointed out that Palindromes only make sense in strings without punctuation, whitespace, or mixed case. Thus, you need to convert your input string, either by removing the unwanted characters or by picking the allowed ones. For the latter, one can imagine:
import string
clean_data = [ch for ch in original_data if ch in string.ascii_letters]
clean_data = ''.join(clean_data).lower()
Having the cleaned version of the input, one might consider the third parameter in slicing of strings, particularly when it's -1 ;)
Does a comparison like
if clean_data[::-1] == clean_data:
....
ring a bell?
One of the primary errors that i spotted is here:
for word in data:
word==word.split()
Here, there are two mistakes:
1. Double equals make no point here.
2. If you wish to split the contents of each iteration of data, then doing like this doesn't change the original list, since you are modifying the duplicate set called word. To achieve your list, do:
for i in range(data):
data[i]=data[i].split()
This may clear your errors

Categories