-1

I did some google searching on how to check if a string has any elements of a list in it and I found this bit of code that works:

if any(i in string for i in list):

I know this works, but I don't really know why. Could you share some insight?

James Mills
  • 18,669
  • 3
  • 49
  • 62
Conyare
  • 105
  • 10
  • 2
    The documentation for [`any`](https://docs.python.org/3/library/functions.html#any) describes exactly what it does. What part of that do you not understand? – abarnert May 17 '15 at 22:52
  • 2
    My guess is that what's _actually_ confusing you here isn't the `any` function, but rather the generator expression being passed as an argument to it. For that, read the tutorial section on [list comprehensions](https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions), then skip ahead to [generators](https://docs.python.org/3/tutorial/classes.html#generators) and generator expressions. – abarnert May 17 '15 at 22:53
  • @abarnert I know that any will return true if any element of the iterator is true. I get confused with how the part of the code before the `for` fits in – Conyare May 17 '15 at 23:48

3 Answers3

6

As the docs for any say:

Return True if any element of the iterable is true. If the iterable is empty, return False. Equivalent to:

def any(iterable):
    for element in iterable:
        if element:
            return True
    return False

So, this is equivalent to:

for element in (i in string for i in list):
    if element:
        return True
return False

… which is itself effectively equivalent to:

for i in list:
    element = i in string
    if element:
        return True
return False

If you don't understand the last part, first read the tutorial section on list comprehensions, then skip ahead to iterators, generators, and generator expressions.

If you want to really break it down, you can do this:

elements = []
for i in list:
    elements.append(i in string)
for element in elements:
    if element:
        return True
return False

That still isn't exactly the same, because a generator expression builds a generator, not a list, but it should be enough to get you going until you read the tutorial sections.


But meanwhile, the point of having any and comprehensions and so on is that you can almost read them as plain English:

if any(i in string for i in list): # Python

if any of the i's is in the string, for each i in the list: # pseudo-English
abarnert
  • 354,177
  • 51
  • 601
  • 671
2
i in string for i in list

This produces an iterable of booleans indicating whether each item in list is in string. Then you check whether any item in this iterable of bools is true.

In effect, you're checking whether any of the items in the list are substrings of string.

Asad Saeeduddin
  • 46,193
  • 6
  • 90
  • 139
1

What's going on here with:

if any(i in string for i in list):    

is best explained by illustrating:

>>> xs = ["Goodbye", "Foo", "Balloon"]
>>> s = "Goodbye World"
>>> [i in s for i in xs]
[True, False, False]
>>> any([i in s for i in xs])
True

If you read the any documentaiton you'll note:

any(iterable) Return True if any element of the iterable is true. If the iterable is empty, return False. Equivalent to:

The list comprehension should be more obvious as it constructs a list of i in s for each element of xs.

Basically (in English) you are returning any match where each sub-string exists in the search string (haystack).

It's important to note as well that any() will short circuit and end on the first True(ish) value it finds. any() can be implement in pure Python like this:

def any(iterable):
    for x in iterable:
        if x:
            return True
    return False
James Mills
  • 18,669
  • 3
  • 49
  • 62