3

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

Alex
  • 146
  • 2
  • 2
  • 10

5 Answers5

12

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.

Rik Poggi
  • 28,332
  • 6
  • 65
  • 82
  • If the wordlist is fixed and this test is run with different sets of letters, pre-converting wordlist to wordsetlist (as in `wordsetlist = map(set, wordlist)`) should pay off quickly. – PaulMcG Feb 25 '12 at 12:40
  • I thought of another thing like it. What if I wanted the output to be the exact input, but not necessarily arranged in the same way? – Alex Feb 25 '12 at 16:54
1
for item in wordlist:
    for character in letters:
        if character in item:
            print item
            break
Ioan Alexandru Cucu
  • 11,981
  • 6
  • 37
  • 39
  • Sorry, this prints item if *any* character in letters is in item; the OP wants to test if *all* characters in letters are in item. (The OP's example has the same bug.) – PaulMcG Feb 25 '12 at 12:37
  • @PaulMcGuire Well, the example confused me as well. Thought he meant a, q OR k... – Ioan Alexandru Cucu Feb 25 '12 at 18:02
1

Here goes your solution:

for item in wordlist:
  b = False
  for c in letters:
    b = b | (item.find(c) != -1)
  if b:
    print item
Boris Strandjev
  • 46,145
  • 15
  • 108
  • 135
  • 1
    `item.find(c) != -1` is *so* last century :) - `c in item` would be the more Pythonic way to do this in these modern times; it's also about 4 times faster in my simple tests. `python -m timeit "'abcdefghijkl'.find('d') != -1"` vs. `python -m timeit "'d' in 'abcdefghijkl'"` gives respective times of .231 usec vs. .0602 usec. Also, you don't do any short-circuiting in your loop - ideally, once you have a failed search, there is no point in searching for any of the other characters in `letters`. Instead of reimplementing `all`, try replacing your code with `b = all(c in item for c in letters)`. – PaulMcG Feb 25 '12 at 12:28
  • All true. Thus - I didn't get any upvotes .I personally also like the others solutions more. However, this was the best I could do using my knowledge. – Boris Strandjev Feb 25 '12 at 12:36
  • No problem, you certainly get points for implementing what the OP *said* he wanted, even though he posted a buggy example! But recent Python versions have added some very nice idioms like `in`, `any`, `all`, and generator expressions, so that your code will collapse down to a very clean list comprehension, as in the submission from @KarlKnechtel. These new idioms are powerful and worth learning and adopting, even I dare say, retrofitting to existing code, for their uniformity, improved performance, built-in short-circuiting, and code reduction without obfuscation. – PaulMcG Feb 25 '12 at 12:50
  • +1 for implementing what the OP *said*, not what the OP *did*! – PaulMcG Feb 25 '12 at 12:52
  • One last point - if letters is the empty string, your code will return *no* items; the set example and `all` will both return all of the items. This is an interesting edge case, and I know there was quite a bit of discussion on how this should go when `any` and `all` were added. In short, `all` will default to True if the generator expression is empty; `any` will default to False. These were chosen based on analogous constructs in logic and set theory. – PaulMcG Feb 25 '12 at 12:59
  • Thank you very much for your time and help! I'm sorry for posting buggy code, I see that now. Thanks! – Alex Feb 25 '12 at 14:12
0
[word for word in wordlist if any(letter in word for letter in 'aqk')]
Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
  • I think you want `all`, not `any`. – PaulMcG Feb 25 '12 at 12:22
  • (I see now that you and @Ioan implemented the OP's example code, which has the same bug - the description however says to "search the list for every single letter in input.") – PaulMcG Feb 25 '12 at 12:43
0

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
Matt Alcock
  • 12,399
  • 14
  • 45
  • 61