Correct one-liner list comprehension - python

I have the following list and string:
words = ['AIBONITO', 'BICINIUM', 'LIMONIUM', 'PICKNICK', 'SILENIUM', 'TITANIUM']
letters = 'ADEOLR'
I want to delete items in the list that contain a letter in the string. The following code does just that.
code:
for letter in letters:
for word in words:
if letter in word:
words.remove(word)
print(words)
output:
['BICINIUM', 'PICKNICK']
Now I would like to convert it to a one-liner. I tried to do it by using the following code:
print([words for letter in letters for word in words if letter not in word])
This gives me a list with 12 items all containing ['BICINIUM', 'PICKNICK']. What do I need to change in the one-liner to obtain the same output as the first piece of code?
I know I can add "[0]" at the end of the one-liner but that's not really clean.

using all allows to do that.
words = ['AIBONITO', 'BICINIUM', 'LIMONIUM', 'PICKNICK', 'SILENIUM', 'TITANIUM']
letters = 'ADEOLR'
result = [word for word in words if all(letter not in word for letter in letters)]
yields:
['BICINIUM', 'PICKNICK']
An alternative uses a set of letters for the same result:
letters = set('ADEOLR')
result = [word for word in words if letters.isdisjoint(word)]

letters = set(letters)
[word for word in words if len(set(word).intersection(letters))==0]
#['BICINIUM', 'PICKNICK']

Related

Python program to generate all possible words by change letter 'c' in the word "ace"

this is my first post here so apologies for formatting in advance, I am trying to write a simple program in Python that takes a word, in this case, the word "ace" and checks all the possible words that can be generated by switching out the letter 'c' with all the letters in the alphabet. What I have tried is turning both my word and the alphabet into lists so I can and create some kind of loop that runs through all the possibilites and eventually cross references them with a dictionary of possible english words (haven't got there yet). I don't have strong a programming background so this has proven to be harder than I thought, my limited work is below, have been at this for a few hours, thanks!
My code...(it doesnt work at the moment)
#take letter ace and input new middle letter
word = list("ace")
alphabet = list("abcdefghijklmnopqrstuvwxyz")
wordnew = []
counter = 0
for word[1] in word:
wordnew = word.replace("c", alphabet[0] if counter < 25)
print(wordnew)
Note that you have to put a variable name to be created between the for and the in — word[1] is not a valid variable name, so your code should fail with a SyntaxError exception.
You can iterate over each letter of the alphabet and create a list of words generated from ace:
alphabet = "abcedfghijklmnopqrstuvwxyz"
words = []
for letter in alphabet:
words.append("ace".replace("c", letter))
You can even do this in one line, using a list comprehension:
words = [ "ace".replace("c", letter) for letter in "abcdefghijklmnopqrstuvwxyz" ]
Note how I didn't have to turn alphabet into a list—in Python, strings are iterable, meaning that you can loop through them just like you can with lists.
Of course, you can print them all, add this at the end:
print(words)
PS: You could also turn "abcdefghijklmnopqrstuvwxyz" into string.ascii_lowercase, though you'll have to import the string module (built into python).
You're close, here is a simple way to do it
>>> word = "ace" #no need to make it a list, you want it to be a string so you can use .replace on it
>>> alphabet = "abcdefghijklmnopqrstuvwxyz" #you can use string in a for loop, in which case they are treated like a list of characters
>>> for letter in alphabet:
print(word.replace("c",letter)) #here you do what you need, here I print it but you can save in a list by doing an .append into one or with a list comprehension which is the prefer mode to make list
aae
abe
ace
ade
aee
afe
age
ahe
aie
aje
ake
ale
ame
ane
aoe
ape
aqe
are
ase
ate
aue
ave
awe
axe
aye
aze
>>>
>>> wordnew = [word.replace("c",letter) for letter in alphabet] #the list comprehension version of the above
>>> wordnew
['aae', 'abe', 'ace', 'ade', 'aee', 'afe', 'age', 'ahe', 'aie', 'aje', 'ake', 'ale', 'ame', 'ane', 'aoe', 'ape', 'aqe', 'are', 'ase', 'ate', 'aue', 'ave', 'awe', 'axe', 'aye', 'aze']
>>>
word = 'ace'
alphabet = list("abcdefghijklmnopqrstuvwxyz")
for letter in alphabet:
print(word.replace('c', letter))
If you want the list of all possible "words" after replacement of letter "c" by any other letter from the alphabet you can simply do the following
word = "ace"
alphabet = "abcdefghijklmnopqrstuvwxyz"
new_words = [word.replace('c', ch) for ch in alphabet]
print(new_words)
word = "ace"
alphabet = list("abcdefghijklmnopqrstuvwxyz")
for letter in alphabet:
wordnew = word.replace("c", letter)
print(wordnew)
You should iterate through the alphabet, not the word.
Assuming you somehow have a list of all the words that exist, this works:
word = "ace"
alphabet = "abcdefghijklmnopqrstuvwxyz"
wordnew = []
counter = 0
# list full of all real words
legitWords = ['ace', 'man', 'math', 'marry' 'age',
'ape', 'are', 'ate', 'awe' 'axe']
for letter in alphabet: # looping through every letter in the alphabet
newWord = word.replace('c', letter) # replaces c with current letter
if newWord in legitWords:
# adds the counter and appends the new word, if it really exists
counter += 1
wordnew.append(newWord)
note that you don't have to convert the strings to lists as you have done, because they are iterable
.

Python: Iterate through string and print only specific words

I'm taking a class in python and now I'm struggling to complete one of the tasks.
The aim is to ask for an input, integrate through that string and print only words that start with letters > g. If the word starts with a letter larger than g, we print that word. Otherwise, we empty the word and iterate through the next word(s) in the string to do the same check.
This is the code I have, and the output. Would be grateful for some tips on how to solve the problem.
# [] create words after "G" following the Assignment requirements use of functions, menhods and kwyowrds
# sample quote "Wheresoever you go, go with all your heart" ~ Confucius (551 BC - 479 BC)
# [] copy and paste in edX assignment page
quote = input("Enter a sentence: ")
word = ""
# iterate through each character in quote
for char in quote:
# test if character is alpha
if char.isalpha():
word += char
else:
if word[0].lower() >= "h":
print(word.upper())
else:
word=""
Enter a sentence: Wheresoever you go, go with all your heart
WHERESOEVER
WHERESOEVERYOU
WHERESOEVERYOUGO
WHERESOEVERYOUGO
WHERESOEVERYOUGOGO
WHERESOEVERYOUGOGOWITH
WHERESOEVERYOUGOGOWITHALL
WHERESOEVERYOUGOGOWITHALLYOUR
The output should look like,
Sample output:
WHERESOEVER
YOU
WITH
YOUR
HEART
Simply a list comprehension with split will do:
s = "Wheresoever you go, go with all your heart"
print(' '.join([word for word in s.split() if word[0].lower() > 'g']))
# Wheresoever you with your heart
Modifying to match with the desired output (Making all uppercase and on new lines):
s = "Wheresoever you go, go with all your heart"
print('\n'.join([word.upper() for word in s.split() if word[0].lower() > 'g']))
'''
WHERESOEVER
YOU
WITH
YOUR
HEART
'''
Without list comprehension:
s = "Wheresoever you go, go with all your heart"
for word in s.split(): # Split the sentence into words and iterate through each.
if word[0].lower() > 'g': # Check if the first character (lowercased) > g.
print(word.upper()) # If so, print the word all capitalised.
Here is a readable and commented solution. The idea is first to split the sentence into a list of words using re.findall (regex package) and iterate through this list, instead of iterating on each character as you did. It is then quite easy to print only the words starting by a letter greater then 'g':
import re
# Prompt for an input sentence
quote = input("Enter a sentence: ")
# Split the sentence into a list of words
words = re.findall(r'\w+', quote)
# Iterate through each word
for word in words:
# Print the word if its 1st letter is greater than 'g'
if word[0].lower() > 'g':
print(word.upper())
To go further, here is also the one-line style solution based on exactly the same logic, using list comprehension:
import re
# Prompt for an input sentence
quote = input("Enter a sentence: ")
# Print each word starting by a letter greater than 'g', in upper case
print(*[word.upper() for word in re.findall(r'\w+', quote) if word[0].lower() > 'g'], sep='\n')
s = "Wheresoever you go, go with all your heart"
out = s.translate(str.maketrans(string.punctuation, " "*len(string.punctuation)))
desired_result = [word.upper() for word in out.split() if word and word[0].lower() > 'g']
print(*desired_result, sep="\n")
Your problem is that you're only resetting word to an empty string in the else clause. You need to reset it to an empty string immediately after the print(word.upper()) statement as well for the code as you've wrote it to work correctly.
That being said, if it's not explicitly disallowed for the class you're taking, you should look into string methods, specifically string.split()

Removing an item from a list

I would like to remove to ignore duplicates in my list. For example, let's say the function checks for words that end with a ''.'' and puts them in a list. I would like to make sure that duplicate words don't go in the list.
Here is what I have so far:
def endwords(sent):
list = []
words = sent.split()
for word in words:
if "." in word:
list.append(word)
# bottom if statment does not work for some reason. thats the one i am trying to fix
if (word == list):
list.remove(word)
return list
How about you check if the word is already in the list before appending it, like so:
def endwords(sent):
wordList = []
words = sent.split()
for word in words:
if "." in word and word not in wordList:
wordList.append(word)
return wordList
You're trying to check if word == list, but that's seeing if the word is equal to the entire list. To check if an element is in a container in python, you can use the in keyword. Alternatively, to check if something is not in a container, you can use not in.
Another option is to use a set:
def endwords(sent):
wordSet = set()
words = sent.split()
for word in words:
if "." in word:
wordSet.add(word)
return wordSet
And to make things a little cleaner, here is a version using set comprehension:
def endwords(sent):
return {word for word in sent.split() if '.' in word}
If you want to get a list out of this function, you can do so like this:
def endwords(sent):
return list({word for word in sent.split() if '.' in word})
Since you said in your question you want to check if the word ends with a '.', you probably also want to use the endswith() function like so:
def endwords(sent):
return list({word for word in sent.split() if word.endswith('.')})
After statement
list = []
you can't use built-in list class and to understand that you can spend about an hour or so, that's why we avoid names of built-ins for our objects.
More at this answer.
function checks for words that end with a ''.''
Statement
"." in word
checks if word contains dot symbol (e.g. "." in "sample.text" will work ok while it simply doesn't end with dot), if you need to check that it ends with dot – use str.endswith method.
I would like to make sure that duplicate words don't go in the list.
just make sure before storing one that it hasn't been stored already.
Finally we can write
def endwords(sent, end='.'):
unique_words = []
words = sent.split()
for word in words:
if word.endswith(end) and word not in unique_words:
unique_words.append(word)
return unique_words
Test
>>>sent = ' '.join(['some.', 'oth.er'] * 10)
>>>unique_words = endwords(sent)
>>>unique_words
['some.']
P. S.
If order doesn't matter – use set, it will take care of duplicates (works only with hashable types, str is hashable):
def endwords(sent, end='.'):
unique_words = set()
words = sent.split()
for word in words:
if word.endswith(end) and word not in unique_words:
unique_words.add(word)
return unique_words
or with set comprehension
def endwords(sent, end='.'):
words = sent.split()
return {word for word in words if word.endswith(end)}
You can add a sample judge for the question.
def endwords(sent):
list = []
words = sent.split()
for word in words:
if "." in word:
if word not in list:
list.append(word)
# bottom if statment does not work for some reason. thats the one i am trying to fix
return list
Why not use a set?
def endwords(sent):
my_list = set()
words = sent.split()
for word in words:
if "." in word:
my_list.add(word)
return my_list
The less verbose way to do it would be using list comprehension, that is
my_list = [word for word in words if '.' in word]
And to ensure the elements aren't duplicated, just use set.
my_list = set(my_list) # No more duplicated values

Word list from text file

I need to create a word list from a text file. The list is going to be used in a hangman code and needs to exclude the following from the list:
duplicate words
words containing less than 5 letters
words that contain 'xx' as a substring
words that contain upper case letters
the word list then needs to be output into file so that every word appears on its own line.
The program also needs to output the number of words in the final list.
This is what I have, but it's not working properly.
def MakeWordList():
infile=open(('possible.rtf'),'r')
whole = infile.readlines()
infile.close()
L=[]
for line in whole:
word= line.split(' ')
if word not in L:
L.append(word)
if len(word) in range(5,100):
L.append(word)
if not word.endswith('xx'):
L.append(word)
if word == word.lower():
L.append(word)
print L
MakeWordList()
You're appending the word many times with this code,
You arn't actually filtering out the words at all, just adding them a different number of timed depending on how many if's they pass.
you should combine all the if's:
if word not in L and len(word) >= 5 and not 'xx' in word and word.islower():
L.append(word)
Or if you want it more readable you can split them:
if word not in L and len(word) >= 5:
if not 'xx' in word and word.islower():
L.append(word)
But don't append after each one.
Think about it: in your nested if-statements, ANY word that is not already in the list will make it through on your first line. Then if it is 5 or more characters, it will get added again (I bet), and again, etc. You need to rethink your logic in the if statements.
Improved code:
def MakeWordList():
with open('possible.rtf','r') as f:
data = f.read()
return set([word for word in data if len(word) >= 5 and word.islower() and not 'xx' in word])
set(_iterable_) returns a set-type object that has no duplicates (all set items must be unique). [word for word...] is a list comprehension which is a shorter way of creating simple lists. You can iterate over every word in 'data' (this assumes each word is on a separate line). if len(word) >= 5 and word.islower() and not 'xx' in word accomplishes the final three requirements (must be more than 5 letters, have only lowercase letters, and cannot contain 'xx').

Search strings in list containing specific letters in random order

I am writing a code in Python 2.7 in which I have defined a list of strings. I then want to search this list's elements for a set of letters. These letters must be in random order. i.e. search the list for every single letter from input.
I have been google'ing around but i haven't found a solution.
Here's what i got:
wordlist = ['mississippi','miss','lake','que']
letters = str(aqk)
for item in wordlist:
if item.find(letters) != -1:
print item
This is an example. Here the only output should be 'lake' and 'que' since these words contain 'a','q' and 'k'.
How can I rewrite my code so that this will be done?
Thanks in advance!
Alex
It would be easy using set():
wordlist = ['mississippi','miss','lake','que']
letters = set('aqk')
for word in wordlist:
if letters & set(word):
print word
Output:
lake
que
Note: The & operator does an intersection between the two sets.
for item in wordlist:
for character in letters:
if character in item:
print item
break
Here goes your solution:
for item in wordlist:
b = False
for c in letters:
b = b | (item.find(c) != -1)
if b:
print item
[word for word in wordlist if any(letter in word for letter in 'aqk')]
Using sets and the in syntax to check.
wordlist = ['mississippi','miss','lake','que']
letters = set('aqk')
for word in wordlist:
if word in letters:
print word

Categories

Resources