replacing list items that fit condition in lambda - python

I've been stuck on a line of my code for a while, and I'm at a loss as to why it returns as it does.
guess = 'a'
word = ['a', 'b', 'c']
board = ['_', '_', '_']
board = list(map(lambda x: guess if word[board.index(x)] == guess else x, board))
print(board)
This returns
['a', 'a', 'a']
Whereas my goal is a return of
['a', '_', '_']
My previous solution was to loop through the list with an increasing value for the index, and to individually check each entry in word against the guess, and to replace the board list at the same index, but I feel that there is a more concise and pythonic way using lambda, I just can't quite get it.

The problem is the list.index method which returns the index of the first match:
list.index(x[, start[, end]])
Return zero-based index in the list of the first item whose value is x. Raises a ValueError if there is no such item. [...]
If you're also interested in a solution: You could simply iterate over both word and board:
guess = 'a'
word = ['a', 'b', 'c']
board = ['_', '_', '_']
board = list(map(lambda x, y: guess if x == guess else y, word, board)) # 3 parameters!
print(board) # ['a', '_', '_']
Given that you want to "replace" you could also use a normal for-loop. That way you would avoid creating and discarding lists all the time:
for idx, char in enumerate(word):
if char == guess:
board[idx] = char

You can use list comprehension:
guess = 'a'
word = ['a', 'b', 'c']
new_word = [i if i == guess else "_" for i in word]
This will give you:
["a", "_", "_"]

You're probably looking for something like this:
board=map(lambda x: x[1] if x[1] == guess else board[x[0]], enumerate(word))

You can use list comprehension as mentioned in the answers, but in your code board will always reset with every guess. I'm guessing you want to keep track of the guesses till all letters are guessed (or till number of guesses) so your loop should have a temporary list and then loop through board to add the new guesses(if found) something like:
word = ['a', 'b', 'c']
board = ['_', '_', '_']
tries = 0
while tries != 3:
guess = raw_input("Enter a guess: ")
tmp = [x if x == guess else '_' for x in word]
for i in xrange(len(board)):
if board[i] == '_':
try:
board[i] = tmp[i]
except IndexError:
pass
print(board)
if '_' not in board:
print('Solved!')
break
tries += 1
if tries == 3:
print('Not solved!')

Related

Trying to remove vowels from user input with function [duplicate]

I'm pretty sure my code is correct but it doesn't seem to returning the expected output:
input anti_vowel("Hey look words") --> outputs: "Hey lk wrds".
Apparently it's not working on the 'e', can anyone explain why?
def anti_vowel(c):
newstr = ""
vowels = ('a', 'e', 'i', 'o', 'u')
for x in c.lower():
if x in vowels:
newstr = c.replace(x, "")
return newstr
The function str.replace(old, new[, max]) don't changes c string itself (wrt to c you calls) just returns a new string which the occurrences of old have been replaced with new. So newstr just contains a string replaced by last vowel in c string that is the o and hence you are getting "Hey lk wrds" that is same as "Hey look words".replace('o', '').
I think you can simply write anti_vowel(c) as:
''.join([l for l in c if l not in vowels]);
What I am doing is iterating over string and if a letter is not a vowel then only include it into list(filters). After filtering I join back list as a string.
Why don't you do it with regexp? According to the documentation, something like this should work:
import re
def anti_vowel(s):
result = re.sub(r'[AEIOU]', '', s, flags=re.IGNORECASE)
return result
If you're using the function often, you could compile the regexp and use the compiled version.
Try String.translate.
>>> "Hey look words".translate(None, 'aeiouAEIOU')
'Hy lk wrds'
string.translate(s, table[, deletechars])
Delete all characters from s that are in deletechars (if present), and then translate the characters using table, which must be a 256-character string giving the translation for each character value, indexed by its ordinal. If table is None, then only the character deletion step is performed.
https://docs.python.org/2/library/string.html#string.Template.substitute
Or if you're using the newfangled Python 3:
>>> table = str.maketrans(dict.fromkeys('aeiouAEIOU'))
>>> "Hey look words.translate(table)
'Hy lk wrds'
Another option is to forego the vowel variable and put the char's to remove in the loop.
def anti_vowel(text):
for i in "aeiouAEIOU":
text = text.replace(i,"")
return text
print anti_vowel("HappIEAOy")
You should do this:
initialize newstr to c, and then
for x in c.lower():
if x in vowels:
newstr = newstr.replace(x, "")
That's because str.replace(old, new[, max]) returns the a copy of the string after replacing the characters:
The method replace() returns a copy of the string in which the
occurrences of old have been replaced with new, optionally restricting
the number of replacements to max.
So, this is the correct code:
def anti_vowel(c):
newstr = c
vowels = ('a', 'e', 'i', 'o', 'u')
for x in c.lower():
if x in vowels:
newstr = newstr.replace(x,"")
return newstr
You can also do it in a more pythonic way:
''.join([x for x in c if x not in vowels])
vowels = ('a', 'e', 'i', 'o', 'u', 'A', 'I', 'E', 'O', 'U')
for char in text:
if char in vowels:
text = text.replace(char, '')
return text
One more simpler way can be extracting the non-vowel characters from string and returning them.
def anti_vowel(text):
newstring=""
for i in text:
if i not in "aeiouAEIOU":
newstring=newstring+i
text=newstring
return text
I know there are many correct solutions on this subject but I thought to add few fun ways of solving this problem.
If you come from a C++/C# or Java, you will tend to use something like compare then action using the index to remove the unwanted entry in a for loop. Python has the Remove and Del functions. Remove function uses the value and
del uses the index.The pythonic solution is in the last function. Lets see how we can do that:
Here we are using the index in a for loop and del function very similar in C++:
def remove_vol(str1):
#list2 = list1 # this won't work bc list1 is the same as list2 meaning same container#
list1 = list(str1)
list2 = list(str1)
for i in range(len(list1)):
if list1[i] in volwes:
vol = list1[i]
x = list2.index(vol)
del list2[x]
print(list2)
Using the remove function:
def remove_vol(str1):
list1 = list(str1)
list2 = list(str1)
for i in list1:
if i in volwes:
list2.remove(i)
print(list2)
Building new string that does not contain the unwanted chars using their indexes:
def remove_vol(str1):
list1 = list(str1)
clean_str = ''
for i in range(len(list1)):
if list1[i] not in volwes:
clean_str += ''.join(list1[i])
print(clean_str)
Same as in the solution in above but using the value:
def remove_vol(str1):
list1 = list(str1)
clean_str = ''
for i in list1:
if i not in volwes:
clean_str += ''.join(i)
print(clean_str)
How you should do it in python? Using list comprehension! It is beautiful:
def remove_vol(list1):
clean_str = ''.join([x for x in list1 if x.lower() not in volwes])
print(clean_str)
def anti_vowel(text):
new=[]
vowels = ("aeiouAEIOU")
for i in text:
if i not in vowels:
new.append(i)
return ''.join(new)
i hope this helps..
def anti_vowel(text):
new_text = ""
for i in text:
if i == 'a' or i == 'A':
pass
elif i == 'e' or i == 'E':
pass
elif i == 'I' or i == 'i':
pass
elif i == 'o' or i == 'O':
pass
elif i == 'u' or i == 'U':
pass
else:
new_text = new_text + i
return new_text
print anti_vowel('Hey look Words!')
My implementation:
# Ask the user for input:
user_input = input("enter a string with some vowels: ")
print("input string: " + str(user_input))
vowels = ('a','e','i','o','u','A','E','I','O','U')
new_string="";
for i in range(0,len(user_input),1):
if user_input[i] in vowels:
print ('found a vowel, removing...')
else:
new_string+=user_input[i]
print("I've removed the vowels for you. You're welcome! The new string is: " + new_string)
A fairly simple approach could be;
def anti_vowel(text):
t = ''
for c in text:
if c in "aeiouAEIOU":
pass
else:
t += c
return t
def anti_vowel(text):
t=""
for c in text:
for i in "ieaouIEAOU":
if c==i:
c=""
else:
c=c
t=t+c
return t

Python lists similitudes

I am looking to get the number of similar characters between two lists.
The first list is:
list1=['e', 'n', 'z', 'o', 'a']
The second list is going to be a word user inputted turned into a list:
word=input("Enter word")
word=list(word)
I'll run this function below to get the number of similitudes in the two lists:
def getSimilarItems(word,list1):
counter = 0
for i in list2:
for j in list1:
if i in j:
counter = counter + 1
return counter
What I don't know how to do is how to get the number of similitudes for each item of the list(which is going to be either 0 or 1 as the word is going to be split into a list where an item is a character).
Help would be VERY appreciated :)
For example:
If the word inputted by the user is afez:
I'd like the run the function:
wordcount= getSimilarItems(word,list1)
And get this as an output:
>>>1 (because a from afez is in list ['e', 'n', 'z', 'o', 'a'])
>>>0 (because f from afez isn't in list ['e', 'n', 'z', 'o', 'a'])
>>>1 (because e from afez is in list ['e', 'n', 'z', 'o', 'a'])
>>>1 (because z from afez is in list ['e', 'n', 'z', 'o', 'a'])
Sounds like you simply want:
def getSimilarItems(word,list1):
return [int(letter in list1) for letter in word]
What I don't know how to do is how to get the number of similitudes
for each item of the list(which is going to be either 0 or 1 as the
word is going to be split into a list where an item is a character).
I assume that instead of counting the number of items in the list, you want to get the individual match result for each element.
For that you can use a dictionary or a list, and return that from your function.
Going off the assumption that the input is going to be the same length as the list,
def getSimilarItems(list1,list2):
counter = 0
list = []
for i in list2:
for j in list1:
if i in j:
list.append(1)
else:
list.append(0)
return list
Based off your edit,
def getSimilarItems(list1,list2):
counter = 0
for i in list2:
if i in list1:
print('1 (because )'+i +' from temp_word is in list'+ str(list1))
else:
print("0 (because )"+i +" from temp_word isn't in list" + str(list1))
Look at Julien's answer if you want a more condensed version (I'm not very good with list comprehension)

How to return a list of strings from a list?

Trying to return a list of strings found in rows of lists. But the order has to be from left to right starting from the top row to lowest without returning duplicates. I'm not sure how to proceed. Would I need to make an IF statement for the letters A to Z if it matches with the list then append them to a new list?
def get_locations(lst):
new_lst = [] # New list?
for i in range(len(lst)):
if 'A' lst[i] <= 'Z' or 'a' <= lst[i] <= 'z': #If strings are A to Z
new_lst.append # Add to new list?
return new_lst
List example: It should return like this get_locations(lst) → ["a","B","A","z","C"]
lst1 = [['.', '.', 'a', 'B'],
['.', '.', 'a', '.'],
['A', '.', '.', 'z'],
['.', '.', '.', 'z'],
['.', '.', 'C', 'C']]
Let's go through the function line by line:
new_lst = [] # New list?
Yes, it creates a new list.
for i in range(len(lst)):
Although this is valid, there is rarely a reason to iterate through list indices in Python. You can iterate through the elements instead. Furthermore, this is a list of lists, so that should be handled as well:
for sublist in lst:
for character in sublist:
After that use character instead of lst[i].
if 'A' lst[i] <= 'Z' or 'a' <= lst[i] <= 'z': #If strings are A to Z
There is a syntax error at 'A' lst[i]. Otherwise, this could work if character is actually a character. If it is a longer string, it may give unexpected results (depending on what you expect):
if 'A' <= character <= 'Z' or 'a' <= character <= 'z':
So, an interesting character was found. Add it to the result?
new_lst.append # Add to new list?
The function should be called:
new_lst.append(character)
BTW, this appends the character regardless of whether it was already in new_lst or not. I gather it should only add a character once:
if character not in new_lst:
new_lst.append(character)
The next line returns the list, but too early:
return new_lst
It should not be indented. It should be outside of the loops, so that the result is returned after all has been looped.
I had a ton of trouble understanding what you meant, but assuming I've figured it out, you weren't too far off:
def get_locations(lst):
new_lst = [] # New list?
for row in lst:
for letter in row:
if ('A' <= letter <= 'Z' or 'a' <= letter <= 'z') and letter not in new_lst: #If strings are A to Z
new_lst.append(letter) # Add to new list?
return new_lst
import re
def get_locations(lst):
new_lst = [] # New list? Yes!
# Iterate directly over "flattened" list. That involves confusing
# nested list comprehension. Look it up, it's fun!
for i in [e for row in lst for e in row]:
# using regular expression gives more flexibility - just to show off :)
if re.match('^[a-zA-Z]+$', i) and i not in new_lst: #deal with duplicates
new_lst.append(i) # Add to new list? yes!
return new_lst # corrected indentation
lst1 = [['.', '.', 'a', 'B'],
['.', '.', 'a', '.'],
['A', '.', '.', 'z'],
['.', '.', '.', 'z'],
['.', '.', 'C', 'C']]
print(get_locations(lst1))
Well if you are not very much concerned about the ordering, The following statement will be powerful enough to keep lengthy methods aside:
ans = {j for i in lst for j in i if j!='.'}
And if maintaining the order is a must to have, then you may consider using the following method:
def get_locations(lst):
ans=[]
for i in lst:
for j in i:
if (j is not '.') and (j not in ans):
ans.append(j)
return ans
You can also use the following generator version for your problem:
def get_locations(lst):
ans=[]
for i in lst:
for j in i:
if (j is not '.') and (j not in ans):
ans.append(j)
yield j
Pretty straightforward. string.ascii_letters is a good shortcut to know for all letters a-Z
import string
def get_chars(lst):
new_list = []
for nested_list in lst:
for char in nested_list:
if char not in new_list and char in string.ascii_letters:
new_list.append(char)
return new_list
Then:
>>> get_chars(lst1)
['a', 'B', 'A', 'z', 'C']

Correct code to remove the vowels from a string in Python

I'm pretty sure my code is correct but it doesn't seem to returning the expected output:
input anti_vowel("Hey look words") --> outputs: "Hey lk wrds".
Apparently it's not working on the 'e', can anyone explain why?
def anti_vowel(c):
newstr = ""
vowels = ('a', 'e', 'i', 'o', 'u')
for x in c.lower():
if x in vowels:
newstr = c.replace(x, "")
return newstr
The function str.replace(old, new[, max]) don't changes c string itself (wrt to c you calls) just returns a new string which the occurrences of old have been replaced with new. So newstr just contains a string replaced by last vowel in c string that is the o and hence you are getting "Hey lk wrds" that is same as "Hey look words".replace('o', '').
I think you can simply write anti_vowel(c) as:
''.join([l for l in c if l not in vowels]);
What I am doing is iterating over string and if a letter is not a vowel then only include it into list(filters). After filtering I join back list as a string.
Why don't you do it with regexp? According to the documentation, something like this should work:
import re
def anti_vowel(s):
result = re.sub(r'[AEIOU]', '', s, flags=re.IGNORECASE)
return result
If you're using the function often, you could compile the regexp and use the compiled version.
Try String.translate.
>>> "Hey look words".translate(None, 'aeiouAEIOU')
'Hy lk wrds'
string.translate(s, table[, deletechars])
Delete all characters from s that are in deletechars (if present), and then translate the characters using table, which must be a 256-character string giving the translation for each character value, indexed by its ordinal. If table is None, then only the character deletion step is performed.
https://docs.python.org/2/library/string.html#string.Template.substitute
Or if you're using the newfangled Python 3:
>>> table = str.maketrans(dict.fromkeys('aeiouAEIOU'))
>>> "Hey look words.translate(table)
'Hy lk wrds'
Another option is to forego the vowel variable and put the char's to remove in the loop.
def anti_vowel(text):
for i in "aeiouAEIOU":
text = text.replace(i,"")
return text
print anti_vowel("HappIEAOy")
You should do this:
initialize newstr to c, and then
for x in c.lower():
if x in vowels:
newstr = newstr.replace(x, "")
That's because str.replace(old, new[, max]) returns the a copy of the string after replacing the characters:
The method replace() returns a copy of the string in which the
occurrences of old have been replaced with new, optionally restricting
the number of replacements to max.
So, this is the correct code:
def anti_vowel(c):
newstr = c
vowels = ('a', 'e', 'i', 'o', 'u')
for x in c.lower():
if x in vowels:
newstr = newstr.replace(x,"")
return newstr
You can also do it in a more pythonic way:
''.join([x for x in c if x not in vowels])
vowels = ('a', 'e', 'i', 'o', 'u', 'A', 'I', 'E', 'O', 'U')
for char in text:
if char in vowels:
text = text.replace(char, '')
return text
One more simpler way can be extracting the non-vowel characters from string and returning them.
def anti_vowel(text):
newstring=""
for i in text:
if i not in "aeiouAEIOU":
newstring=newstring+i
text=newstring
return text
I know there are many correct solutions on this subject but I thought to add few fun ways of solving this problem.
If you come from a C++/C# or Java, you will tend to use something like compare then action using the index to remove the unwanted entry in a for loop. Python has the Remove and Del functions. Remove function uses the value and
del uses the index.The pythonic solution is in the last function. Lets see how we can do that:
Here we are using the index in a for loop and del function very similar in C++:
def remove_vol(str1):
#list2 = list1 # this won't work bc list1 is the same as list2 meaning same container#
list1 = list(str1)
list2 = list(str1)
for i in range(len(list1)):
if list1[i] in volwes:
vol = list1[i]
x = list2.index(vol)
del list2[x]
print(list2)
Using the remove function:
def remove_vol(str1):
list1 = list(str1)
list2 = list(str1)
for i in list1:
if i in volwes:
list2.remove(i)
print(list2)
Building new string that does not contain the unwanted chars using their indexes:
def remove_vol(str1):
list1 = list(str1)
clean_str = ''
for i in range(len(list1)):
if list1[i] not in volwes:
clean_str += ''.join(list1[i])
print(clean_str)
Same as in the solution in above but using the value:
def remove_vol(str1):
list1 = list(str1)
clean_str = ''
for i in list1:
if i not in volwes:
clean_str += ''.join(i)
print(clean_str)
How you should do it in python? Using list comprehension! It is beautiful:
def remove_vol(list1):
clean_str = ''.join([x for x in list1 if x.lower() not in volwes])
print(clean_str)
def anti_vowel(text):
new=[]
vowels = ("aeiouAEIOU")
for i in text:
if i not in vowels:
new.append(i)
return ''.join(new)
i hope this helps..
def anti_vowel(text):
new_text = ""
for i in text:
if i == 'a' or i == 'A':
pass
elif i == 'e' or i == 'E':
pass
elif i == 'I' or i == 'i':
pass
elif i == 'o' or i == 'O':
pass
elif i == 'u' or i == 'U':
pass
else:
new_text = new_text + i
return new_text
print anti_vowel('Hey look Words!')
My implementation:
# Ask the user for input:
user_input = input("enter a string with some vowels: ")
print("input string: " + str(user_input))
vowels = ('a','e','i','o','u','A','E','I','O','U')
new_string="";
for i in range(0,len(user_input),1):
if user_input[i] in vowels:
print ('found a vowel, removing...')
else:
new_string+=user_input[i]
print("I've removed the vowels for you. You're welcome! The new string is: " + new_string)
A fairly simple approach could be;
def anti_vowel(text):
t = ''
for c in text:
if c in "aeiouAEIOU":
pass
else:
t += c
return t
def anti_vowel(text):
t=""
for c in text:
for i in "ieaouIEAOU":
if c==i:
c=""
else:
c=c
t=t+c
return t

Algorithmic string in python?

I have a string say a = "awxxxyyw".
It should remove all the consecutive elements from the string and return me final string as "a".
ie in 1st iteration xxx seems to be consecutive, so remove xxx, then string becomes awyyw.
2nd iteration removes yy. string becomes aww.
3rd iteration remove ww. returns a
Here is my code.
Where I'm going wrong?
def func(string,pointer):
print pointer
for i in range(pointer,len(string)):
flag=0
temp = i
print temp,pointer
try:
while(string[i-1] == string[i]):
print string
i+= 1
flag = 1
except : break
if flag == 0 :
continue
else:
string = string[0:temp] + string[i+1:len(string)]
func(string, temp)
return string
string = "awxxxyyw"
print func(string,1)
The problem with your code is that you’re only ever removing one character at a time, and so repeated sequences will be reduced to a single character, but that single character will stick around at the end. For example, your code goes from “xxx” to “xx” to “x”, but since there’s only a single “x” left that “x” is not removed from the string. Adapt your code to remove all of the consecutive repeated characters and your problem will be fixed.
I think this is easiest to do with an iterated regular expression substitution:
def remove_dups(s):
import re
pat = re.compile(r"(.)\1+")
while True:
news = pat.sub("", s)
if s == news:
break
s = news
return s
print remove_dups("awxxxyyw") # "a"
print remove_dups("aaxyyza") # "xza"
You need to modify your code to remove all consecutive repeated letters, rather than one at a time. Retaining your recursion:
def func(string):
for i in range(len(string) - 1):
if string[i] == string[i+1]:
j = i + 1
while j < len(string) and string[j] == string[i]:
j += 1
return func(string[:i] + string[j:])
return string
You can do this using itertools.groupby, it allows you to group adjacent similar items:
from itertools import groupby
def solve(x):
while True:
lis = [list(g) for k, g in groupby(x)]
print lis
#if any item in lis has length != 1 then remove all such items
if any(len(x) != 1 for x in lis):
x = ''.join([''.join(x) for x in lis if len(x)==1])
else:
return ''.join([''.join(x) for x in lis])
s = "awxxxyyw"
print solve(s)
print
s = 'aaacccxxxka'
print solve(s)
Output:
[['a'], ['w'], ['x', 'x', 'x'], ['y', 'y'], ['w']] #remove ['x', 'x', 'x'], ['y', 'y'] here
[['a'], ['w', 'w']] #remove ['w', 'w'] here
[['a']] #nothing to remove, returns this as answer.
a
[['a', 'a', 'a'], ['c', 'c', 'c'], ['x', 'x', 'x'], ['k'], ['a']]
[['k'], ['a']]
ka
A working demo:
def func(s):
stack = ['']
idx = 0
while idx < len(s):
if s[idx] == stack[-1]:
el = s[idx]
stack.pop()
while idx < len(s) and s[idx] == el:
idx += 1
else:
stack.append(s[idx])
idx += 1
return ''.join(stack)
print func('awxxxyyw')
'a'
print func('awxyw')
'awxyw'
print func('a')
'a'
print func('abcdefghijklmnoprstuvxywzzwyxvutsrponmlkjihgfedcba')
''

Categories