Timmay
Timmay

Reputation: 85

Use Function to Return a List of Words Containing Required Letters

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

Answers (5)

jfs
jfs

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))

Output

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)))

Output

Words that contain all given vowels:
...
vivaciousness's
vocabularies
voluntaries
voluptuaries
warehousing

Upvotes: 0

Hugh Bothwell
Hugh Bothwell

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

Andrew White
Andrew White

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

salezica
salezica

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

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

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

Related Questions