What i want is remove the words which have more than two consecutive vowels in it. So input:
s = " There was a boat in the rain near the shore, by some mysterious lake"
Output:
[boat,rain,near,mysterious]
So here is my code.
I was just wondering if there is any better way to do this or is this efficient enough.And if you can do this with python dict or lists are ok? :) I'm new to python so yeah. :) comments would be nice.
def change(s):
vowel = ["a","e","i","o","u"]
words = []
a = s[:].replace(",","").split()
for i in vowel:
s = s.replace(i, "*").replace(",","")
for i,j in enumerate(s.split()):
if "**" in j:
words.append(a[i])
return words
Alternatively, you could always use regular expressions and list comprehension to get the list of words:
>>> import re
>>> [x for x in s.split() if re.search(r'[aeiou]{2}', x)]
['boat', 'rain', 'near', 'mysterious']
s.split() splits the sentence into a list of words. The expression [x for x in s.split()] considers each word in this list in turn.
The re.search(r'[aeiou]{2}', x) part of the expression searches each word for two consecutive letters from the group [aeiou]. Only if two consecutive vowels are found is the word put in the new list.
using sets:
First method using set.intersection will only find non identical consecutive pairs so oo would not be a match:
s = " There was a boat in the rain near the shore, by some mysterious lake"
vowels = "aeiouAEIOU"
print([x for x in s.split() if any(len(set(x[i:i+2]).intersection(vowels))== 2 for i in range(len(x))) ])
['boat', 'rain', 'near', 'mysterious']
Method 2 uses set.issubset so now identical consecutive pairs will be considered a match.
using set.issubset with a function using the yield from python 3 syntax which might be more appropriate and indeed to catch repeated identical vowels :
vowels = "aeiouAEIOU"
def get(x, step):
yield from (x[i:i+step] for i in range(len(x[:-1])))
print([x for x in s.split() if any(set(pr).issubset(vowels) for pr in get(x, 2))])
Or again in a single list comp:
print([x for x in s.split() if any(set(pr).issubset(vowels) for pr in (x[i:i+2] for i in range(len(x[:-1]))))])
Finally make vowels a set and check if it is a set.issuperset of any pair of chars:
vowels = {'a', 'u', 'U', 'o', 'e', 'i', 'A', 'I', 'E', 'O'}
def get(x, step):
yield from (x[i:i+step] for i in range(len(x[:-1])))
print([x for x in s.split() if any(vowels.issuperset(pr) for pr in get(x, 2))])
Using pairwise iteration:
from itertools import tee
def pairwise(iterable):
a, b = tee(iter(iterable))
next(b)
return zip(a,b)
vowels = 'aeiouAEIOU'
[word for word in s.split() if any(
this in vowels and next in vowels for this,next in pairwise(word))]
Use regular expressions instead:
import re
s = 'There was a boat in the rain near the shore, by some mysterious lake'
l = [i for i in s.split(' ') if re.search('[aeiou]{2,}', i)]
print ' '.join(l) # back to string
Using product instead:
from itertools import product
vowels = 'aiueo'
comb = list(product(vowels, repeat=2))
s = " There was a boat in the rain near the shore, by some mysterious lake"
def is2consecutive_vowels(word):
for i in range(len(word)-1):
if (word[i], word[i+1]) in comb:
return True
return False
print [word for word in s.split() if is2consecutive_vowels(word)]
# ['boat', 'rain', 'near', 'mysterious']
or if you don't need to use any external library:
vowels = 'aeiou'
def is2consecutive_vowels2(word):
for i in range(len(word)-1):
if word[i] in vowels and word[i+1] in vowels:
return True
return False
print [word for word in s.split() if is2consecutive_vowels2(word)]
# ['boat', 'rain', 'near', 'mysterious']
This one is even quicker than regex solution!
a=[]
def count(s):
c=0
t=s.split()
for i in t:
for j in range(len(i)-1):
w=i[j]
u=i[j+1]
if u in "aeiou" and w in "aeiou":
c+=1
if(c>=1):
a.append(i)
c=0
return(a)
print(count("There was a boat in the rain near the shore, by some mysterious lake"))
Related
I have a list like this,
['Therefore', 'allowance' ,'(#)', 't(o)o', 'perfectly', 'gentleman', '(##)' ,'su(p)posing', 'man', 'his', 'now']
Expected output:
['Therefore', 'allowance' ,'(#)', 'too', 'perfectly', 'gentleman', '(##)' ,'supposing', 'man', 'his', 'now']
Removing the brackets is easy by using .replace(), but I don't want to remove the brackets from strings (#) and (##).
my code:
ch = "()"
for w in li:
if w in ["(#)", "(##)"]:
print(w)
else:
for c in ch:
w.replace(c, "")
print(w)
but this doesn't remove the brackets from the words.
You can use re.sub. In particular, note that it can take a function as repl parameter. The function takes a match object, and returns the desired replacement based on the information the match object has (e.g., m.group(1)).
import re
lst = ['Therefore', 'allowance', '(#)', 't(o)o', 'perfectly', 'gentleman', '(##)', 'su(p)posing', 'man', 'his', 'now']
def remove_paren(m):
return m.group(0) if m.group(1) in ('#', '##') else m.group(1)
output = [re.sub(r"\((.*?)\)", remove_paren, word) for word in lst]
print(output) # ['Therefore', 'allowance', '(#)', 'too', 'perfectly', 'gentleman', '(##)', 'supposing', 'man', 'his', 'now']
def removeparanthesis(s):
a=''
for i in s:
if i not in '()':
a+=i
return a
a = ['Therefore', 'allowance' , '(#)' , 't(o)o' , 'perfectly' , 'gentleman' , '(##)' , 'su(p)posing', 'man', 'his', 'now']
b=[]
for i in a:
if i == '(#)' or i == '(##)':
b.append(i)
else:
b.append(removeparanthesis(i))
print(b)
#I just created a function to remove parenthesis to those with not having them as a start and end
Give this a try!
Here, I define another empty array. And by looping in the original array to append the words again except the ones that we don't need.
At first, as you can see we got two loops. In the second one, we loop through each character and whenever we encounter a ( or ) we skip it and continue appending our string word.
If you notice that; to keep the (#) and (##) we skip the second loop but do not forget to add them again to the new list.
li = ["Therefore", "allowance", "(#)", "t(o)o" , "perfectly", "gentleman", "(##)", "su(p)posing", "man", "his", "now"]
new_li = []
for index, w in enumerate(li):
if w in ["(#)", "(##)"]:
new_li.append(w)
continue
new_word = ""
for c in w:
if c == "(" or c == ")":
continue
new_word = new_word + c
new_li.append(new_word)
print(new_li)
I have a list as an input which contains words, these words sometimes contain non-ascii letter characters, I need to filter out the entire word if they contain letters that are not in the ascii list.
So the if the input is:
words = ['Hello', 'my','dear', 'de7ar', 'Fri?ends', 'Friends']
I need the Output:
['Hello', 'my', 'dear', Friends']
words = ['Hello', 'my','dear', 'de7ar', 'Fri?ends', 'Friends']
al = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
ascii_letters = [char for char in al]
filtered_words=[]
I tried it with this:
for el in words:
try:
words in ascii_letters
except FALSE:
filtered_words.append(el)
and this
filtered words = [ele for ele in words if all(ch not in ele for ch in ascii_letters)]
but both of them do not result in what I need - I do understand why but since I have only been learning python for a week I fail to adjust them to make them do what I want them to, maybe someone knows how to handle this (without using any libraries)?
Thanks
You could check whether your alphabet is a superset of the words:
>>> [*filter(set(al).issuperset, words)]
['Hello', 'my', 'dear', 'Friends']
Btw, better don't hardcode that alphabet (I've seen quite a few people do that and forget letters) but import it:
from string import ascii_letters as al
You need to iterate trough the words in the words list to check whether all letters are ion ASCII or you can use the all() function:
words = ['Hello', 'my','dear', 'de7ar', 'Fri?ends', 'Friends']
al = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
ascii_letters = [char for char in al]
out = []
for word in words:
not_in_ascii = False
for letter in word:
if letter not in ascii_letters:
not_in_ascii = True
if not_in_ascii:
continue
out.append(word)
It is also possible with list comprehension and all() as you tried:
out = [word for word in words if all([letter in ascii_letters for letter in word])]
[i for i in words if i.isalpha()]
Result:
['Hello', 'my', 'dear', 'Friends']
I wanna return a list of words containing a letter disregarding its case.
Say if i have sentence = "Anyone who has never made a mistake has never tried anything new", then f(sentence, a) would return
['Anyone', 'has', 'made', 'a', 'mistake', 'has', 'anything']
This is what i have
import re
def f(string, match):
string_list = string.split()
match_list = []
for word in string_list:
if match in word:
match_list.append(word)
return match_list
You don't need re. Use str.casefold:
[w for w in sentence.split() if "a" in w.casefold()]
Output:
['Anyone', 'has', 'made', 'a', 'mistake', 'has', 'anything']
You can use string splitting for it, if there is not punctuation.
match_list = [s for s in sentence.split(' ') if 'a' in s.lower()]
Here's another variation :
sentence = 'Anyone who has never made a mistake has never tried anything new'
def f (string, match) :
match_list = []
for word in string.split () :
if match in word.lower ():
match_list.append (word)
return match_list
print (f (sentence, 'a'))
I have below dictionary that I created in such a way that the key is the length of the values.
{4: {'lost', 'lust', 'list', 'last', 'lest', 'blue'}, 5: {'beryl'}, 8: {'blowlamp', 'blimbing', 'bluejays', 'jigsawed'}, 9: {'blistered', 'oospheres', 'blackcaps', 'blastular', 'blotchier', 'troweller'}, 10: {'blancmange', 'blackguard', 'volcanizes'}, 6: {'blague', 'blacks', 'blonde', 'blocks'}, 7: {'blawort', 'blinder', 'blender', 'blonder', 'blunder', 'blander'}}
I want to pull out a list of values in this dictionary in such a way that the vowel comes at the same place for 5 words like
[lost,lust,list,last,lest],[blinder,blender,blonder,blunder,blander]]
I am not having any idea on how to get the list in such a way. One way I thought could be through regex but on what basis do I match? The length of the words could be anything and vowel could be anywhere.
PS this is a codewars question. https://www.codewars.com/kata/vowel-alternations/train/python
My approach so far that I got the values with same length in a dictionary so that I can work on the values. I just have no idea how to work on the values.
It would be helpful if anyone can explain me what they are thinking and what is the best way to do this.
The rest of the code
mdict={}
rev_multidict = {}
for i in words:
for sublist in i:
mdict[sublist] = len(sublist)
for key, value in mdict.items():
rev_multidict.setdefault(value, set()).add(key)
for key,value in rev_multidict.items():
i = rev_multidict[key]
print(i)
You could check the first string for the location of the vowels and generate a regex string to match. Every char maps to either '[aeiou]' or '.' depending on if it's a vowel or not. Why you do with 'y' is up to you.
the following code is the start of one way of approaching it:
#!/usr/bin/python
import re
words = 'last lest best list '.split()
words1 = 'blander wigwam blunder slender'.split()
print("word list one: {}".format(words))
print('')
aoa = [re.split('[aeiou]', word) for word in words]
for item in aoa:
print(item)
print('\n')
print("word list two: {}".format(words1))
print('')
aoa1 = [re.split('[aeiou]', word) for word in words1]
for item in aoa1:
print(item)
the output is:
word list one: ['last', 'lest', 'best', 'list']
['l', 'st']
['l', 'st']
['b', 'st']
['l', 'st']
word list two: ['blander', 'wigwam', 'blunder', 'slender']
['bl', 'nd', 'r']
['w', 'gw', 'm']
['bl', 'nd', 'r']
['sl', 'nd', 'r']
The regex splits on vowels. If you look closely at the output of the split, you will notice that for the words that should match, the corresponding list index values are the same. Perhaps you can iterate over the lists and do a comparison.
That is left up to you...
Assuming you want to print out only if the output list contains 5 words:
text = {4: {'lost', 'lust', 'list', 'last', 'lest', 'blue'}, 5: {'beryl'}, 8: {'blowlamp', 'blimbing', 'bluejays', 'jigsawed'}, 9: {'blistered', 'oospheres', 'blackcaps', 'blastular', 'blotchier', 'troweller'}, 10: {'blancmange', 'blackguard', 'volcanizes'}, 6: {'blague', 'blacks', 'blonde', 'blocks'}, 7: {'blawort', 'blinder', 'blender', 'blonder', 'blunder', 'blander'}}
vowels = "aeiou"
for i in range(4,10):
words = text[i]
rep_idx = []
for word in words:
for letter in vowels:
if letter in word:
idx = word.index(letter)
if idx not in rep_idx:
word_list = []
for word in words:
if word[idx] in vowels:
word_list.append(word)
if len(word_list) == 5:
print ("{}, Vowel Index: {}".format(word_list, idx))
rep_idx.append(idx)
Output:
>>>
['lust', 'lest', 'list', 'lost', 'last'], Vowel Index: 1
['blonder', 'blender', 'blinder', 'blander', 'blunder'], Vowel Index: 5
['blistered', 'blackcaps', 'troweller', 'blastular', 'blotchier'], Vowel Index: 2
['blistered', 'troweller', 'oospheres', 'blastular', 'blotchier'], Vowel Index: 7
Ok, for the codewars Question (I've taken different approach than you, so I didn't use your code):
First you define a simple function changing all vowels for some (here a dollar sign) character:
from collections import Counter
def translate(word):
for ch in 'eyuioa':
if ch in word:
word=word.replace(ch,'$')
return word
Then you define a function, that takes list of words as an input (eg. ['last', 'lest', 'list', 'lost', 'lust'])) that counts occurences of each translated word, and find that translated word that occurs 5 times. Store it in a list and add a [None] just in case the list is empty (word not found), so that you don't get an error. Then simply print all words that meet a condition.
def find_solutions(input_list):
tuples_list = list(map(lambda x: (x,translate(x)),input_list))
counting = Counter(map(lambda x: x[1], tuples_list))
desired_pattern = [x for x,y in dict(counting).items() if y ==5] + [None]
return [x for x, y in tuples_list if y==desired_pattern[0]]
example:
find_solutions(['last', 'lest', 'list', 'lost', 'lust'])
This would be very robust approach, but it seems to work:
vowels = 'aeiou'
def find_solutions(words):
solutions = []
vowel_list = list(vowels)
cases = []
for word in words:
for i, l in enumerate(word):
if l in vowel_list:
c = list(word)
temp = []
for vowel in vowel_list:
c[i] = vowel
temp.append(''.join(c))
cases.append(temp)
for case in cases:
if all([item in words for item in case]):
if case not in solutions:
solutions.append(case)
return solutions
The code:
def anti_vowel(text):
string1 = list(text)
for i in string1:
if i=='A'or i=='a' or i=='E'or i=='e'or i=='O'or i=='o' or \
i=='I'or i=='i' or i=='U' or i=='u':
del(string1[string1.index(i)])
string2 = ''.join(string1)
return string2
Gives an error:
Your function fails on anti_vowel("Hey look Words!").
It returns "Hy lk Words!" when it should return "Hy lk Wrds!".
I don't know how to delete that "o" in "words". Can you tell me what's wrong?
If you just want to remove vowels from strings this is an easy way to do it:
word = "hello world"
w = filter(lambda x: x not in 'aeiouAEIOU', word)
print w
Output:
hll wrld
This looks like a good place to be using regular expressions...
import re
re_vowels = re.compile(r'[AaEeIiOoUu]')
def anti_vowel(text):
return re_vowels.sub('', text)
Results in 'hy lk Wrds!'
But if you have to fix the code you have, try this...
def anti_vowel(text):
string1 = list(text)
for c in xrange(len(string1)-1,-1,-1):
i = string1[c]
if i=='A'or i=='a' or i=='E'or i=='e'or i=='O'or i=='o' or \
i=='I'or i=='i' or i=='U' or i=='u':
del(string1[c])
string2 = ''.join(string1)
return string2
Or...
def anti_vowel(text):
return ''.join([c for c in text if c.lower() not in 'aeiou'])
In your code you are trying to delete something that doesn't exist anymore. If you are going to iterate through a list while deleting elements, iterate through it in reverse order (or use list comprehensions).
your code is messy and not nice you can do it a easy way by setting vowels and comparing them to the value like below. This then will do a replace on the vowels which match in the string.
def anti_vowel(text):
string1 = text
vowels = ('a', 'e', 'i', 'o', 'u')
for x in text.lower():
if x in vowels:
string1 = string1.replace(x,"")
return string1