1

I don't understand why any() is not working the way I expect it to. Below, I want to say, if any of the cities in the cities list are in the phrase.split(), return True. But why does it return false when phrase.split() is ['replacement', 'windows', 'in', 'seattle', 'wa'] and 'seattle' is clearly in the phrase.split() list?

>>> cities = ['seattle', 'san antonio', 'denver']
>>> phrase = 'replacement windows in seattle wa'
>>> any(cities) in phrase.split()
False
>>> 'seattle' in phrase.split()
True
nbro
  • 15,395
  • 32
  • 113
  • 196
Jarad
  • 17,409
  • 19
  • 95
  • 154
  • possible duplicate of [How exactly does the python any() function work?](http://stackoverflow.com/questions/16505456/how-exactly-does-the-python-any-function-work) – nbro Feb 02 '15 at 04:15

5 Answers5

5

Becuse any(cities) return True, and True is not in the list:

>>> cities = ['seattle', 'san antonio', 'denver']
>>> phrase = 'replacement windows in seattle wa'
>>> any(cities)
True
>>> True in phrase.split()
False
>>> any(cities) in phrase.split()
False

You can use this way to see if any city in the list:

>>> [i for i in cities if i in phrase.split()]
['seattle']
>>> any(i for i in phrase.split() if i in cities)
True
lqhcpsgbl
  • 3,694
  • 3
  • 21
  • 30
  • @zoosuck Thank you, this is very helpful in helping me understand why any() was returning False. – Jarad Feb 02 '15 at 04:45
  • 2
    Your `any` is backwards -- should be `any(i in cities for i in phrase.split())` –  Feb 02 '15 at 06:12
  • You did not change it. You just change a list comprehension into a generator... Compare `any((i for i in phrase.split() if i in cities))` to `any(i in cities for i in phrase.split())` in the first form, phrase is being split repeatedly –  Feb 02 '15 at 06:38
3

Because in any(cities) will return True for a non-empty list, or False for an empty list - that value is never contained in your membership test. Also note that splitting by space is going to separate san antonio into two words, so using this approach you won't be able to match it. An alternative is instead to use a regular expression:

import re

cities = ['seattle', 'san antonio', 'denver']
phrase = 'replacement windows in seattle wa'

has_city = re.compile('|'.join(sorted(cities, key=len, reverse=True))).search
if has_city(phrase):
    # do whatever

This is very similar to if any(city in phrase for city in cities) (it will find san antonio) but requires multiple parses over phrase instead of the regex doing it just once.

You might also wish to consider re.escaping the strings and applying word boundaries depending on the exact criteria for matching.

Jon Clements
  • 138,671
  • 33
  • 247
  • 280
  • Thank you very much for your well thought-out response. I would have never thought of your suggestion. I also was wondering about how to handle multi-word cities since `split()` spits on spaces so thanks for helping me on this aspect as well. – Jarad Feb 02 '15 at 04:42
1

Try this statement

any(word in phrase.split() for word in cities)

Your original statement is not really testing every word in "cities" to every word in "phrase.split()."

radsine
  • 66
  • 2
0
any(x for x in cities if x in phrase.split())
Takahiro
  • 1,222
  • 10
  • 11
0

Here goes another way to do it correctly,

any(word in cities for word in phrase.split())

Or,

any(True for word in phrase.split() if word in cities)
sujoy
  • 135
  • 2
  • 7