jlwebuser
jlwebuser

Reputation: 49

Using in operator to match items in a tuple

I am trying to understand why the in operator below does not also match and print (4, 'foobar'), and ('foobar', 5) (it matches the rest). Trying to nail down my understanding of the in with tuples. I was trying to match all tuples that had "foo" or "bar", or "foobar" in any part of the tuple.

ls = [(1, 'foo'), ('bar2'), ('foo', 'bar', 3), (4, 'foobar'), ('foobar', 5), ('foobar')]
print [x for x in ls if 'foo' in x or 'bar' in x]
[(1, 'foo'), 'bar2', ('foo', 'bar', 3), 'foobar']

Upvotes: 2

Views: 198

Answers (2)

Mad Physicist
Mad Physicist

Reputation: 114478

For a tuple, 'foo' in x means "is there an element of x that equals 'foo'", not "is there an element of x that contains 'foo'".

To do the latter, you could do something like

any('foo' in y for y in x)

However, for a string, 'foo' in x means "is 'foo' a substring of x".

Additionally, a single element in parentheses (e.g. ('bar2') and ('foobar')) does not make a tuple. To make a tuple, you generally need a comma in the parentheses: ('bar2',) and ('foobar',). Both of these elements match because they are not tuples and contain the right substring.

If you are looking specifically for foo, bar and foobar, not something like barfoo, just add an additional or to the comprehension:

[x for x in ls if 'foo' in x or 'bar' in x or 'foobar' in x]

You could generalize using any by doing something like

search_terms = ('foo', 'bar', 'foobar')
[x for x in ls if any(a in x for a in search_terms)]

Upvotes: 3

Leo K
Leo K

Reputation: 5354

Because ('bar2') is not a tuple, but just the string 'bar2' (and 'bar' is in that string), while ('foobar', 1) is a tuple and 'bar' is not one of ('foobar', 1).

'in' works differently on a list/tuple and on a single string. When applied to a string, it asks "is 'foo' a substring?". When applied to a list/tuple, it asks "is 'foo' equal to one of the list/tuple items?".

Upvotes: 2

Related Questions