21
if 'string1' in line: ...

... works as expected but what if I need to check multiple strings like so:

if 'string1' or 'string2' or 'string3' in line: ...

... doesn't seem to work.

0

8 Answers 8

47
if any(s in line for s in ('string1', 'string2', ...)):
Sign up to request clarification or add additional context in comments.

Comments

7

If you read the expression like this

if ('string1') or ('string2') or ('string3' in line):

The problem becomes obvious. What will happen is that 'string1' evaluates to True so the rest of the expression is shortcircuited.

The long hand way to write it is this

if 'string1' in line or 'string2' in line or 'string3' in line:

Which is a bit repetitive, so in this case it's better to use any() like in Ignacio's answer

Comments

2

or does not behave that way. 'string1' or 'string2' or 'string3' in line is equivalent to ('string1') or ('string2') or ('string3' in line), which will always return true (actually, 'string1').

To get the behavior you want, you can say if any(s in line for s in ('string1', 'string2', 'string3')):.

Comments

2

You have this confusion because you don't understand how logical operators work with respect to strings.

Python considers empty strings as False and Non empty Strings as True.

Generally:

a and b evaluates to b if a is True, a otherwise.

a or b evaluates to a if a is True, b otherwise.

Therefore, every time you put in a non empty string in place of string1 the condition will evaluate to True.

Comments

1
if 'string1' in line or 'string2' in line or 'string3' in line:

Would that be fine for what you need to do?

1 Comment

Ofcourse, thats what I tried but I needed a more readable and efficient method. :)
1

Using map and lambda

a = ["a", "b", "c"]
b = ["a", "d", "e"]
c = ["1", "2", "3"]

# any element in `a` is a element of `b` ?
any(map(lambda x:x in b, a))
>>> True

# any element in `a` is a element of `c` ?
any(map(lambda x:x in c, a)) # any element in `a` is a element of `c` ?
>>> False

and high-order function

has_any = lambda b: lambda a: any(map(lambda x:x in b, a))

# using ...
f1 = has_any( [1,2,3,] )
f1( [3,4,5,] )
>>> True
f1( [6,7,8,] )
>>> False

Comments

0

also as for "or", you can make it for "and". and these are the functions for even more readablity:

returns true if any of the arguments are in "inside_of" variable:

def any_in(inside_of, arguments):
  return any(argument in inside_of for argument in arguments)

returns true if all of the arguments are in "inside_of" variable:

same, but just replace "any" for "all"

Comments

-1

You can use "set" methods

line= ["string1","string2","string3","string4"]

# check any in
any_in = not set(["string1","string2","not_in_line"]).isdisjoint(set(line))

# check all in
all_in = set(["string1","string2"]).issubset(set(line))

print(f"any_in: {any_in}, all_in:{all_in}")
# Results: 
#    any_in: True, all_in:True

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.