How to check if exactly one value in an iterable resolves to True?
Rise to the top 3% as a developer or hire one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------
Music by Eric Matyas
https://www.soundimage.org
Track title: Unforgiving Himalayas Looping
--
Chapters
00:00 How To Check If Exactly One Value In An Iterable Resolves To True?
00:44 Accepted Answer Score 9
01:03 Answer 2 Score 5
01:19 Answer 3 Score 0
02:27 Thank you
--
Full question
https://stackoverflow.com/questions/2279...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #list #expression
#avk47
ACCEPTED ANSWER
Score 9
Your title disagrees with the body of your question, but I'll answer the title.
You can sum boolean values. Check if it's equal to 1 (or whatever value you'd like):
>>> a = [True, True, False]
>>> sum(a)
2
>>> b = ['hey', '', 'a string']
>>> sum(map(bool,b))
2
ANSWER 2
Score 5
You can do it using count:
>>> a=[True, True, False]
>>> if a.count(True) == 1:
... print 'Hello'
... else:
... print 'Sorry'
Sorry
Examples
>>> [True, False].count(True) == 1
True
>>> [True, True, False].count(True) == 1
False
>>> [True, True, False].count(False) == 1
True
ANSWER 3
Score 0
So, the general format for this is something like this:
test = [True, True, False]
if len([x for x in test if x]) == 1:
# Do something
Of course, the above is just testing if x is boolean True, but you could put any kind of comparison there.
You might say, but isn't that inefficient? Not really, if you really want exactly N items - you'd have to check them all anyways to see if there is another True lurking in there.
For the case where it's 'N or more' items, you can kind of (ab)use generators to do this:
from itertools import islice
result = True
g = (x for x in test if x)
if len(list(islice(g, 2))) == 2:
# do something
This is a bit of a shortcut, since it will stop as soon as it sees the number of items and not walk farther through the generator. If you wanted to use this form for an exact count, it has a small advantage over the list form:
if len(list(islice(g, 2))) == 2 and not any(g):
# do something
Why does this have a small advantage? In the passing case, we still have to look through every other item to make sure there are exactly 2 Trues in the list. But in the failing case, as soon as we see another True, the any will shortcut and you won't walk through the rest of the list.