Reputation: 85
I am trying to write a function that takes a string, and checks every letter in that string against every letter, in every line, in a list of words. The code I have written is:
def uses_all(required):
fin = open('words.txt')
for line in fin:
for letter in line:
if letter not in required:
pass
return line
When I try to have only words that contain vowels returned it is only returning the last line in the file.
>>> uses_all('aeiou')
'zymurgy\n'
Upvotes: 0
Views: 6576
Reputation: 414207
uses_any()
The name uses_all()
seems to contradict the intent "I try to have only words that contain vowels returned". Here's a possible correction:
def uses_any(letters):
"""Yield words that contain any of the `letters`."""
with open('words.txt') as fin:
for word in fin: # if there is a single word per line then just say so
if any(letter in letters for letter in word):
# or set(letters).issuperset(word)
yield word.strip() # remove leading/trailing whitespace
uses_only()
Another interpretation could be:
def uses_only(input_words, required_letters, only=True):
"""Yield words from `input_words` that contain `required_letters`.
if `only` is true then a word is constructed entirely from`required_letters`
(but — may be not from *all* `required_letters`).
"""
present = all if only else any
for word in input_words:
if present(letter in required_letters for letter in word):
yield word #note: no .strip(), .lower(), etc here
with open('/etc/dictionaries-common/words') as fin:
words = fin.read().decode('utf-8').lower().splitlines()
print 'Words that constructed entirely from given vowels:'
print '\n'.join(uses_only(words, u'aeiou'))
print 'Words that contain any given vowels:'
print '\n'.join(uses_only(words, u'aeiou', only=False))
Words that constructed entirely from given vowels:
a
au
e
eu
i
io
o
u
a
e
i
o
u
Words that contain any given vowels:
...
épées
étude
étude's
études
uses_all()
If the intent is: "I try to have only words that contain [all] vowels returned [but other letters are allowed too]" then:
def uses_all(input_words, required_letters):
"""Yield `input_words` that contain all `required_letters`."""
required_letters = frozenset(required_letters)
for word in input_words:
if required_letters.issubset(word):
yield word
print 'Words that contain all given vowels:'
print '\n'.join(uses_all(unique_justseen(words), u'aeiou'))
Where words
is defined in the previous example and unique_justseen()
is:
from itertools import imap, groupby
from operator import itemgetter
def unique_justseen(iterable, key=None):
"""List unique elements, preserving order.
Remember only the element just seen.
"""
# unique_justseen('AAAABBBCCDAABBB') --> A B C D A B
# unique_justseen('ABBCcAD', str.lower) --> A B C A D
return imap(next, imap(itemgetter(1), groupby(iterable, key)))
Words that contain all given vowels:
...
vivaciousness's
vocabularies
voluntaries
voluptuaries
warehousing
Upvotes: 0
Reputation: 56644
class WordMatcher(object):
@classmethod
def fromFile(cls, fname):
with open(fname) as inf:
return cls(inf)
def __init__(self, words):
super(WordMatcher,self).__init__()
self.words = set(word.strip().lower() for word in words)
def usesAllLetters(self, letters):
letters = set(letters)
for word in self.words:
if all(ch in word for ch in letters):
yield word
wordlist = WordMatcher.fromFile('words.txt')
vowelWords = list(wordlist.usesAllLetters('aeiou'))
Upvotes: 0
Reputation: 53496
You are only returning line which is just the loop variable. You need to build a list of answers. I am not sure what you where trying to do with the pass which is a no-op but here is a version of your code which should work...
def uses_all(required):
fin = open('words.txt')
answer = []
for line in fin:
should_take = True
for letter in required:
if letter not in required:
should_take = False
if should_take ==True:
answer.append(line)
return answer
Upvotes: 1
Reputation: 76919
Well, the function you´ve written iterates through the file without doing anything, and then returns the last line, so the behavior you see is kinda expected.
Try this:
def uses_all(required):
ret = []
fin = open('words.txt')
for line in fin:
# Let´s try and find all our required letters in that word.
for letter in required:
if letter not in line:
break # We`re missing one! Break!
else: # else block executes if no break occured
ret.append(line)
return ret
It`s a lousy implementation, but it should work.
Upvotes: 2
Reputation: 798626
Lines yielded from iterating over a file have the EOL at the end. Strip that first.
Also, the question doesn't match the logic in the code.
Upvotes: 2