Question

I'm looking for a simple method to check if only one variable in a list of variables has a True value. I've looked at this logical xor post and is trying to find a way to adapt to multiple variables and only one true.

Example

>>>TrueXor(1,0,0)
True

>>>TrueXor(0,0,1)
True

>>>TrueXor(1,1,0)
False

>>>TrueXor(0,0,0,0,0)
False
Was it helpful?

Solution

There isn't one built in but it's not to hard to roll you own:

def TrueXor(*args):
    return sum(args) == 1

Since "[b]ooleans are a subtype of plain integers" (source) you can sum the list of integers quite easily and you can also pass true booleans into this function as well.

So these two calls are homogeneous:

TrueXor(1, 0, 0)
TrueXor(True, False, False)

If you want explicit boolean conversion: sum( bool(x) for x in args ) == 1.

OTHER TIPS

I think the sum-based solution is fine for the given example, but keep in mind that boolean predicates in python always short-circuit their evaluation. So you might want to consider something more consistent with all and any.

def any_one(iterable):
    it = iter(iterable)
    return any(it) and not any(it)
>>> def f(*n):
...     n = [bool(i) for i in n]
...     return n.count(True) == 1
...
>>> f(0, 0, 0)
False
>>> f(1, 0, 0)
True
>>> f(1, 0, 1)
False
>>> f(1, 1, 1)
False
>>> f(0, 1, 0)
True
>>>

The question you linked to already provides the solution for two variables. All you have to do is extend it to work on n variables:

import operator

def only_one_set(*vars):
    bools = [bool(v) for v in vars]
    return reduce(operator.xor, bools, False)

>>> a, b, c, d, e = False, '', [], 10, -99
>>> only_one_set(a, b, c, d)
True
>>> only_one_set(a, b, c, d, e)
False

Here's my straightforward approach. I've renamed it only_one since xor with more than one input is usually a parity checker, not an "only one" checker.

def only_one(*args):
    result = False
    for a in args:
        if a:
            if result:
                return False
            else:
                result = True
    return result

Testing:

>>> only_one(1,0,0)
True
>>> only_one(0,0,1)
True
>>> only_one(1,1,0)
False
>>> only_one(0,0,0,0,0)
False
>>> only_one(1,1,0,1)
False
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top