The World’s Largest Online Community for Developers

';
python - How to test multiple variables against a value? - LavOzs.Com
python if-statement comparison match boolean-logic

I'm trying to make a function that will compare multiple variables to an integer and output a string of three letters. I was wondering if there was a way to translate this into Python. So say:

```
x = 0
y = 1
z = 3
mylist = []
if x or y or z == 0 :
mylist.append("c")
if x or y or z == 1 :
mylist.append("d")
if x or y or z == 2 :
mylist.append("e")
if x or y or z == 3 :
mylist.append("f")
```

which would return a list of

```
["c", "d", "f"]
```

Is something like this possible?

You misunderstand how boolean expressions work; they don't work like an English sentence and guess that you are talking about the same comparison for all names here. You are looking for:

```
if x == 1 or y == 1 or z == 1:
```

`x`

and `y`

are otherwise evaluated on their own (`False`

if `0`

, `True`

otherwise).

You can shorten that using a containment test against a tuple:

```
if 1 in (x, y, z):
```

or better still:

```
if 1 in {x, y, z}:
```

using a `set`

to take advantage of the constant-cost membership test (`in`

takes a fixed amount of time whatever the left-hand operand is).

When you use `or`

, python sees each side of the operator as *separate* expressions. The expression `x or y == 1`

is treated as first a boolean test for `x`

, then if that is False, the expression `y == 1`

is tested.

This is due to operator precedence. The `or`

operator has a lower precedence than the `==`

test, so the latter is evaluated *first*.

However, even if this were *not* the case, and the expression `x or y or z == 1`

was actually interpreted as `(x or y or z) == 1`

instead, this would still not do what you expect it to do.

`x or y or z`

would evaluate to the first argument that is 'truthy', e.g. not `False`

, numeric 0 or empty (see boolean expressions for details on what Python considers false in a boolean context).

So for the values `x = 2; y = 1; z = 0`

, `x or y or z`

would resolve to `2`

, because that is the first true-like value in the arguments. Then `2 == 1`

would be `False`

, even though `y == 1`

would be `True`

.

The same would apply to the inverse; testing multiple values against a single variable; `x == 1 or 2 or 3`

would fail for the same reasons. Use `x == 1 or x == 2 or x == 3`

or `x in {1, 2, 3}`

.

Your problem is more easily addressed with a dictionary structure like:

```
x = 0
y = 1
z = 3
d = {0: 'c', 1:'d', 2:'e', 3:'f'}
mylist = [d[k] for k in [x, y, z]]
```

As stated by Martijn Pieters, the correct, and fastest, format is:

```
if 1 in {x, y, z}:
```

Using his advice you would now have separate if-statements so that Python will read each statement whether the former were `True`

or `False`

. Such as:

```
if 0 in {x, y, z}:
mylist.append("c")
if 1 in {x, y, z}:
mylist.append("d")
if 2 in {x, y, z}:
mylist.append("e")
...
```

This will work, but *if* you are comfortable using dictionaries (see what I did there), you can clean this up by making an initial dictionary mapping the numbers to the letters you want, then just using a for-loop:

```
num_to_letters = {0: "c", 1: "d", 2: "e", 3: "f"}
for number in num_to_letters:
if number in {x, y, z}:
mylist.append(num_to_letters[number])
```

The direct way to write `x or y or z == 0`

is

```
if any(map((lambda value: value == 0), (x,y,z))):
pass # write your logic.
```

But I dont think, you like it. :) And this way is ugly.

The other way (a better) is:

```
0 in (x, y, z)
```

BTW lots of `if`

s could be written as something like this

```
my_cases = {
0: Mylist.append("c"),
1: Mylist.append("d")
# ..
}
for key in my_cases:
if key in (x,y,z):
my_cases[key]()
break
```

If you ARE very very lazy, you can put the values inside an array. Such as

```
list = []
list.append(x)
list.append(y)
list.append(z)
nums = [add numbers here]
letters = [add corresponding letters here]
for index in range(len(nums)):
for obj in list:
if obj == num[index]:
MyList.append(letters[index])
break
```

You can also put the numbers and letters in a dictionary and do it, but this is probably a LOT more complicated than simply if statements. That's what you get for trying to be extra lazy :)

One more thing, your

```
if x or y or z == 0:
```

will compile, but not in the way you want it to. When you simply put a variable in an if statement (example)

```
if b
```

the program will check if the variable is not null. Another way to write the above statement (which makes more sense) is

```
if bool(b)
```

Bool is an inbuilt function in python which basically does the command of verifying a boolean statement (If you don't know what that is, it is what you are trying to make in your if statement right now :))

Another lazy way I found is :

```
if any([x==0, y==0, z==0])
```

To check if a value is contained within a set of variables you can use the inbuilt modules `itertools`

and `operator`

.

For example:

Imports:

```
from itertools import repeat
from operator import contains
```

Declare variables:

```
x = 0
y = 1
z = 3
```

Create mapping of values (in the order you want to check):

```
check_values = (0, 1, 3)
```

Use `itertools`

to allow repetition of the variables:

```
check_vars = repeat((x, y, z))
```

Finally, use the `map`

function to create an iterator:

```
checker = map(contains, check_vars, check_values)
```

Then, when checking for the values (in the original order), use `next()`

:

```
if next(checker) # Checks for 0
# Do something
pass
elif next(checker) # Checks for 1
# Do something
pass
```

etc...

This has an advantage over the `lambda x: x in (variables)`

because `operator`

is an inbuilt module and is faster and more efficient than using `lambda`

which has to create a custom in-place function.

Another option for checking if there is a non-zero (or False) value in a list:

```
not (x and y and z)
```

Equivalent:

```
not all((x, y, z))
```

I think this will handle it better:

```
my_dict = {0: "c", 1: "d", 2: "e", 3: "f"}
def validate(x, y, z):
for ele in [x, y, z]:
if ele in my_dict.keys():
return my_dict[ele]
```

Output:

```
print validate(0, 8, 9)
c
print validate(9, 8, 9)
None
print validate(9, 8, 2)
e
```

Set is the good approach here, because it orders the variables, what seems to be your goal here. `{z,y,x}`

is `{0,1,3}`

whatever the order of the parameters.

```
>>> ["cdef"[i] for i in {z,x,y}]
['c', 'd', 'f']
```

This way, the whole solution is O(n).

If you want to use if, else statements following is another solution:

```
myList = []
aList = [0, 1, 3]
for l in aList:
if l==0: myList.append('c')
elif l==1: myList.append('d')
elif l==2: myList.append('e')
elif l==3: myList.append('f')
print(myList)
```

All of the excellent answers provided here concentrate on the specific requirement of the original poster and concentrate on the `if 1 in {x,y,z}`

solution put forward by Martijn Pieters.

What they ignore is the broader implication of the question:

**How do I test one variable against multiple values?**

The solution provided will not work for partial hits if using strings for example:

Test if the string "Wild" is in multiple values

```
>>> x = "Wild things"
>>> y = "throttle it back"
>>> z = "in the beginning"
>>> if "Wild" in {x, y, z}: print (True)
...
```

or

```
>>> x = "Wild things"
>>> y = "throttle it back"
>>> z = "in the beginning"
>>> if "Wild" in [x, y, z]: print (True)
...
```

for this scenario it's easiest to convert to a string

```
>>> [x, y, z]
['Wild things', 'throttle it back', 'in the beginning']
>>> {x, y, z}
{'in the beginning', 'throttle it back', 'Wild things'}
>>>
>>> if "Wild" in str([x, y, z]): print (True)
...
True
>>> if "Wild" in str({x, y, z}): print (True)
...
True
```

It should be noted however, as mentioned by `@codeforester`

, that word boundries are lost with this method, as in:

```
>>> x=['Wild things', 'throttle it back', 'in the beginning']
>>> if "rot" in str(x): print(True)
...
True
```

the 3 letters `rot`

do exist in combination in the list but not as an individual word. Testing for " rot " would fail but if one of the list items were "rot in hell", that would fail as well.

The upshot being, be careful with your search criteria if using this method and be aware that it does have this limitation.

```
d = {0:'c', 1:'d', 2:'e', 3: 'f'}
x, y, z = (0, 1, 3)
print [v for (k,v) in d.items() if x==k or y==k or z==k]
```

This code may be helpful

```
L ={x, y, z}
T= ((0,"c"),(1,"d"),(2,"e"),(3,"f"),)
List2=[]
for t in T :
if t[0] in L :
List2.append(t[1])
break;
```

One line solution:

```
mylist = [{0: 'c', 1: 'd', 2: 'e', 3: 'f'}[i] for i in [0, 1, 2, 3] if i in (x, y, z)]
```

Or:

```
mylist = ['cdef'[i] for i in range(4) if i in (x, y, z)]
```

You can try the method shown below. In this method, you will have the freedom to specify/input the number of variables that you wish to enter.

```
mydict = {0:"c", 1:"d", 2:"e", 3:"f"}
mylist= []
num_var = int(raw_input("How many variables? ")) #Enter 3 when asked for input.
for i in range(num_var):
''' Enter 0 as first input, 1 as second input and 3 as third input.'''
globals()['var'+str('i').zfill(3)] = int(raw_input("Enter an integer between 0 and 3 "))
mylist += mydict[globals()['var'+str('i').zfill(3)]]
print mylist
>>> ['c', 'd', 'f']
```

Maybe you need direct formula for output bits set.

```
x=0 or y=0 or z=0 is equivalent to x*y*z = 0
x=1 or y=1 or z=1 is equivalent to (x-1)*(y-1)*(z-1)=0
x=2 or y=2 or z=2 is equivalent to (x-2)*(y-2)*(z-2)=0
```

Let's map to bits: `'c':1 'd':0xb10 'e':0xb100 'f':0xb1000`

Relation of isc (is 'c'):

```
if xyz=0 then isc=1 else isc=0
```

Use math if formula https://youtu.be/KAdKCgBGK0k?list=PLnI9xbPdZUAmUL8htSl6vToPQRRN3hhFp&t=315

[c]: `(xyz=0 and isc=1) or (((xyz=0 and isc=1) or (isc=0)) and (isc=0))`

[d]: `((x-1)(y-1)(z-1)=0 and isc=2) or (((xyz=0 and isd=2) or (isc=0)) and (isc=0))`

...

Connect these formulas by following logic:

- logic
`and`

is the sum of squares of equations - logic
`or`

is the product of equations

and you'll have a total equation express sum and you have total formula of sum

then sum&1 is c, sum&2 is d, sum&4 is e, sum&5 is f

After this you may form predefined array where index of string elements would correspond to ready string.

`array[sum]`

gives you the string.

It can be done easily as

```
for value in [var1,var2,var3]:
li.append("targetValue")
```

The most mnemonic way of representing your pseudo-code in Python would be:

```
x = 0
y = 1
z = 3
mylist = []
if any(v == 0 for v in (x, y, z)):
mylist.append("c")
if any(v == 1 for v in (x, y, z)):
mylist.append("d")
if any(v == 2 for v in (x, y, z)):
mylist.append("e")
if any(v == 3 for v in (x, y, z)):
mylist.append("f")
```

Looks like you're building some kind of Caesar cipher.

A much more generalized approach is this:

```
input_values = (0, 1, 3)
origo = ord('c')
[chr(val + origo) for val in inputs]
```

outputs

```
['c', 'd', 'f']
```

Not sure if it's a desired side effect of your code, but the order of your output will always be sorted.

If this is what you want, the final line can be changed to:

```
sorted([chr(val + origo) for val in inputs])
```

To test multiple variables with one single value: `if 1 in {a,b,c}:`

To test multiple values with one variable: `if a in {1, 2, 3}:`

You can use dictionary :

```
x = 0
y = 1
z = 3
list=[]
dict = {0: 'c', 1: 'd', 2: 'e', 3: 'f'}
if x in dict:
list.append(dict[x])
else:
pass
if y in dict:
list.append(dict[y])
else:
pass
if z in dict:
list.append(dict[z])
else:
pass
print list
```

This will help you.

```
def test_fun(val):
x = 0
y = 1
z = 2
myList = []
if val in (x, y, z) and val == 0:
myList.append("C")
if val in (x, y, z) and val == 1:
myList.append("D")
if val in (x, y, z) and val == 2:
myList.append("E")
test_fun(2);
```

Related

Calling a function of a module by using its name (a string)

How do I check whether a file exists without exceptions?

How do I return multiple values from a function?

Using global variables in a function

How do I sort a dictionary by value?

How to make a chain of function decorators?

“Least Astonishment” and the Mutable Default Argument

How does Python's super() work with multiple inheritance?

Pythonic way to create a long multi-line string

Why is “1000000000000000 in range(1000000000000001)” so fast in Python 3?

Calling a function of a module by using its name (a string)

How do I check whether a file exists without exceptions?

How do I return multiple values from a function?

Using global variables in a function

How do I sort a dictionary by value?

How to make a chain of function decorators?

“Least Astonishment” and the Mutable Default Argument

How does Python's super() work with multiple inheritance?

Pythonic way to create a long multi-line string

Why is “1000000000000000 in range(1000000000000001)” so fast in Python 3?