Python anti-vowel function - some vowels cannot be removed [duplicate] - python

This question already has answers here:
How to remove items from a list while iterating?
(25 answers)
Correct code to remove the vowels from a string in Python
(13 answers)
Closed 6 years ago.
I just started to learn Python in codacademy. I was trying to do anti-vowel function, but found the following problem with 'u'.
def anti_vowel(text):
a = []
for i in text:
a.append(i)
for item in a:
if item in "aeiouAEIOU":
a.remove(item)
print ''.join(a)
print anti_vowel("Hey You!")
print anti_vowel("Hey look Words!")
print anti_vowel("aeiouAEIOU")
It printed
"Hy Yu!"
"Hy lk Words!"
"eoAIU"
Instead of
"Hy Y!"
"Hy lk Wrds!"
""
Somehow, some vowels was not removed es expected.
I found many alternatives for the function.
However, please help me identify the mistake of the current code.

There's no need to use remove, and there's no need to iterate twice. Rather, as you iterate, check whether the item is a vowel and only append if it is not.
def anti_vowel(text):
a = []
for i in text:
if i not in "aeiouAEIOU":
a.append(i)
print ''.join(a)

When you look very closely at the remaining vowels, you can see that all those vowels remain that immediately follow one another. In your last example, a (removed) e (stays) i (removed) o (stays) and so on.
This is because you are iterating over a list and at the same time you are modifying it.
To solve the problem, you should make a copy of the list. Then you can iterate over the original one while modifying the copy.

Removing items while iterating is not a good idea.
Do it in one line with a generator comprehension passed to str.join
def anti_vowel(text):
return ''.join(item for item in text if item not in "aeiouAEIOU")
or maybe more performant using a set for faster letter lookup (not sure converting to lowercase would speed this up since it creates a new string for that)
s=set("aeiouAEIOU")
def anti_vowel(text):
return ''.join(item for item in text if item not in s)

Like others have already stated, you are modifying your list while iterating through it. I did want to suggest a python built-in option for this task, though for 3.x > Python > 2.6:
print "Hey You!".translate(None, "aeiouAEIOU")
In Python 3.x you'll need to take account for the standard Unicode string and translate it first:
translation = dict.fromkeys(map(ord, "aeiouAEIOU"), None)
print("Hey You!".translate(translation))

def anti_vowel(text):
a = []
for i in text:
a.append(i)
b = a[:]
for item in a:
if item in "aeiouAEIOU":
b.remove(item)
print (''.join(b))
print (anti_vowel("Hey You!"))
print (anti_vowel("Hey look Words!"))
print (anti_vowel("aeiouAEIOU"))

Why not try recursively like this?
def anti_vowel(s):
if not s:
return s
elif s[0] in "aeiouAEIOU":
return anti_vowel(s[1:])
return s[0] + anti_vowel(s[1:])
print (anti_vowel("Hey You!"))
print (anti_vowel("Hey look Words!"))
print (anti_vowel("aeiouAEIOU"))
Output:
Hy Y!
Hy lk Wrds!

you are removing item from list while traversing so thats creating a problem.
Moreover there is no need to traverse the so many times.
you could use:
def anti_vowel(text):
a = []
for i in text:
if i not in "aeiouAEIOU":
a.append(i)
print ''.join(a)
or I would say instead of using list use string like this :
def anti_vowel(text):
a = ""
for item in text:
if item not in "aeiouAEIOU":
a+=item
print a
Edited:
using ''.join(list) is faster than using string cancatenation as pointed out by #jean in the comment section.

You could also join the result of a list comprehension, like:
def anti_vowel(text):
return "".join([char for char in text if char not in "aeiouAEIOU"])
Be sure to let your functions return their results if you want the function to do more than just printing to the terminal (for example if you want to use the returned value somehow). There's no need to print the results of a function that prints its result and returns None (which is the case if there are no return statements inside).
The [char for char in text ...] part of the list comprehension is simply a for loop over the characters in the string named text. The [... if char not in "aeiouAEIOU"] excludes the characters who are present in the "aeiouAEIOU" string. Finally, "".join([ ... ]) merges the non-excluded characters together to form a string which by the return statement is returned.

Related

Complications in for loop for Capitalizing words in a string in Python 3

I'm Trying to capitalize the words in a string using this technique:
def solve(s):
if len(s)>0 and len(s)<1000:
li= s.split(" ")
for i in li:
i= i.capitalize()
return " ".join(li)
But this just doesn't seem to work. On the other hand while I'm using the below technique, it works perfectly fine. Please help me with the use of two kinds "for" loop in two cases.
def solve(s):
if len(s)>0 and len(s)<1000:
li= s.split(" ")
for i in range(len(li)):
li[i]= li[i].capitalize()
return " ".join(li)
In the above line you are not throwing the capitalized value to the li variable, youare just replacing the value of the actual element:
for i in li:
i= i.capitalize()
In your second approach you are throwing the value to li variable again, that's why it works on the second case.
You do realize strings have a builtin method to do exactly that?
>>> "hello world this is a test".title()
'Hello World This Is A Test'
>>>

How would I detect duplicate elements of a string from another string in python?

So how would I go about finding a duplicate element of a string from another string in python using a for the most part one-to-two line or a quick fix?
for example,
str1 = "abccde"
str2 = "abcde"
# gets me c
Through the use of str2, finding there was a duplicate element in str1, so detecting that str1 has a duplicate of an element in str2. Not sure if there's a way through .count to do that, like str1.count(str2) or something.
I'm using this contextually for my hangman assignment and I'm a beginner coder, so we are using mostly built-in functions and the basics for the assignments, and there's a piece of my code within my loop that will keep printing because it dings the double letters.
Ex. hello, grinding, concoction.
So I pretty much made a "used" string, and I am trying to compare that to my correct letters list, and the guesses are 'appended' so I can avoid that.
note: they will be inputted, so I won't be able to say or just hardcode the letter c if that makes sense.
Thank you!
Using set with str.count:
def find_dup(str1, str2):
return [i for i in set(str1) if str1.count(i) > 1 and i in set(str2)]
Output:
find_dup("abccde", "abcde")
# ['c']
find_dup("abcdeffghi" , "aaaaaabbbbbbcccccddeeeeefffffggghhiii") # from comment
# ['f']
My guess is that maybe you're trying to write a method similar to:
def duplicate_string(str1: str, str2: str) -> str:
str2_set = set(str2)
if len(str2_set) != len(str2):
raise ValueError(f'{str2} has duplicate!')
output = ''
for char in str1:
if char in str2_set:
str2_set.remove(char)
else:
output += char
return output
str1 = "abccccde"
str2 = "abcde"
print(duplicate_string(str1, str2))
Output
ccc
Here, we would first raise an error, if str2 itself had a duplicate. Then, we'd loop through str1, either remove a char from the str1_set or append the duplicate in an output string.
You are basically searching a diff function between the two strings. Adapting this beautiful answer
import difflib
cases=[('abcccde', 'abcde')]
for a,b in cases:
print('{} => {}'.format(a,b))
for i,s in enumerate(difflib.ndiff(a, b)):
if s[0]==' ': continue
elif s[0]=='-':
print(u'The second string is missing the "{}" in position {} of the first string'.format(s[-1],i))
elif s[0]=='+':
print(u'The first string is missing the "{}" in position {} of the second string'.format(s[-1],i))
print()
Output
abcccde => abcde
The second string is missing the "c" in position 3 of the first string
The second string is missing the "c" in position 4 of the first string

python simple loop_.join function

I'm an amateur learner and would like to have more ideas on these.
This is what I want,
paper_doll('Hello') --> 'HHHeeellllllooo'
Here is my code and it doesn't work, but I have no ideas why.
def paper_doll(text):
for i in range(0,len(text)-1):
return ''.join(text[i]*3)
paper_doll('Hello')
The result became 'HHH'.
Understood the following would work,
def paper_doll(text):
result = ''
for char in text:
result += char * 3
return result
But why .join doesn't work in this case?
def paper_doll(text):
ret=[]
for i in text:
ret.append(i*3)
return ''.join(ret)
Should work. This returns each 3 letter iteration, joined together.
First, your code does not work because the return statement exits from the function on the first iteration loop, so it triples only the first letter, and that's all:
def paper_doll(text):
for i in range(0,len(text)-1): # on 1st iteration: i = 0
return ''.join(text[i]*3) # on 1st iteration: text[i] equals 'H' ==> 'HHH' is returned
Secondly, here is a solution using comprehension, which is well adapted in your case to iterate over each character of a string:
def paper_doll(text):
return ''.join(i*3 for i in text)
print(paper_doll('Hello')) # HHHeeellllllooo
Your initial problem was the return in your iteration. This short circuits the rest of the loop... as noted in other answers.
python can iterate through a string for you. Another answer using list comprehension:
def paper_doll(text):
return ''.join([char*3 for char in text])
Add to a string during the loop, return the result:
def paper_doll(text):
s = ''
for i in range(0,len(text)):
s += ''.join(text[i]*3)
return s
print(paper_doll('Hello'))
Output:
HHHeeellllllooo
(I also removed the -1 in range so you get three "o"s)

How to combine individual characters in one string in python [duplicate]

This question already has answers here:
How to print without a newline or space
(26 answers)
Closed 6 years ago.
I have code like this:
def reverse(text):
l=len(text)
while ((l-1)!=0):
print (str(text[l-1]))
l=l-1
print (str(text[0]))
a=reverse("abc!de#fg")
The output is:
g
f
#
e
d
!
c
b
a
but I want to combine these individual characters and want out put like this:
gf#ed!cba
To print without the newline at the end of each line do:
print('text', end='')
To take a list of characters and make them one string, do:
''.join(list_of_characters)
def reverse(text):
if len(text) <= 1:
return text
return reverse(text[1:]) + text[0]
print (reverse('abc!de#fg'))
The simplest way to reverse a string:
In [1]: a = "abc!de#fg"
In [2]: print(a[::-1])
gf#ed!cba
The python print statement adds a newline by default. An easy way to print without newlines is
sys.stdout.write('some text')
# or
print('some text', end='')
You will need to concatenate them and then print the string result.
This is because the function print automatically does a break line.
A fix would be:
def reverse(text):
l = len(text)
aux = ''
while l-1 != 0:
aux += str(text[l-1])
l = l - 1
print (aux)
a = reverse("abc!de#fg")`
P.S: Try to avoid redundant parenthesis =)
Hey try to put the print value in variable and print that at the end. Like this.
def reverse(text):
l=len(text)
output = ""
while ((l-1)!=0):
output += (str(text[l-1]))
l=l-1
output +=(str(text[0]))
print output
a=reverse("abc!de#fg")
Hope this helps
In Python, the simplest way to reverse a Sequence is with a slice:
>>> string="abc!de#fg"
>>> print(string[::-1])
gf#ed!cba
Slicing will give you a copy of the sequence in reverse order.
In general, you want a function to do one thing. Returning a value and printing some output are separate concerns, so they should not be conflated in the same function. If you have a function that returns a reversed string, you can simply print the function:
print(reverse("abc"))
Then, you can see that your actual algorithm is fine, if not entirely Pythonic:
def reverse(text):
l=len(text)
output = ""
while ((l-1)!=0):
output += (str(text[l-1]))
l=l-1
output +=(str(text[0]))
return output
You can clearly see now that it's the print function in your way.

Finding Digits in a String

I'm very new to python and am having trouble with the following bit of code. The aim is to create a function that prints all the integers within a string.
def get_digits(str1):
for i in str1:
if i.isdigit():
return i
However it is only returning the first integer in the string, and I am unsure on how to get it to print all of them.
My apologies if the question is stupid, I have looked around for a while on this site and others and haven't been able to work it out.
Condensed down into a list comprehension
def get_digits(strval):
return [i for i in strval if i.isdigit()]
print get_digits('432jfsd5fs')
print ''.join(get_digits('432jfsd5fs'))
Returns
['4', '3', '2', '5']
4325
Whenever you return from a function, the function stops executing. I would recommend a generator here, which allows you to return an iterable from a function without writing much code.
This question smacks of homework, so I'm not going to give the full answer, but I would recommend looking at this StackOverflow answer for a great explanation of generators and the yield keyword.
>>> def print_digits(str1):
... for i in str1:
... if i.isdigit():
... print i
...
>>> print_digits("a12b3")
1
2
3
print prints things. return sends the answer back to whatever ran the function. i guess you are confusing the two because if you run a function within python it prints whatever is returned. but that is only because python is trying to be helpful and show you the result; it's not how you normally print things.
if you really want return the digits, and print them elsewhere, then one way to do it is build a list of results:
>>> def get_digits(str1):
... results = []
... for i in str1:
... if i.isdigit():
... results.append(i)
... return results
...
>>> print(get_digits("a12b3"))
['1', '2', '3']
Your function quits after it finds the first digit. In order for it to return all the digits, collect the results in a list.
def get_digits(str1):
digits = []
for i in str1:
if i.isdigit():
digits.append(i)
return digits
You can also simplify your function, by using a list comprehension:
def get_digits(str1):
return [d for d in str1 if d.isdigit()]
If you just want to print the results and not return them, replace return i with print i in your original function.
You can loop through the digits and return a list of them, like this:
def get_digits(str1):
digits = [] # define new list
for i in str1:
if i.isdigit():
digitis.append(i) # i is a digit, append to list
return digits # return the list of digits
def get_digits(str1):
numbers = ""
for i in str1:
if i.isdigit():
numbers = numbers + i
return numbers
Simple explanation:
# your code
def get_digits(str1):
for i in str1:
if i.isdigit():
return i
when a function meets return i, it stops its further execution, and return the value.
Since others has explained in detail, I'll just put more solutions for reference:
#1. Using generator
def get_digits_generator(str1):
for i in str1:
if i.isdigit():
yield i
#2. Returning a list of digits
def get_digits_list(str1):
list_of_digits = []
for i in str1:
if i.isdigit():
list_of_digits.append(i)
return list_of_digits
#3. List comprehension
str1 = "asdbh12njasdo29ns"
list_of_digits = [character for character in str1 if character.isdigit()]
import re
re.findall('\d', str1)
a=""
def get_digits(str1):
for i in str1:
if i.isdigit():
a=a&i
return a
try it like this. Because you return while you find the first digital.

Categories