The best answer here is to use all(), which is the builtin for this situation. We combine this with a generator expression to produce the result you want cleanly and efficiently. For example:
>>> items = [[1, 2, 0], [1, 2, 0], [1, 2, 0]]
>>> all(flag == 0 for (_, _, flag) in items)
True
>>> items = [[1, 2, 0], [1, 2, 1], [1, 2, 0]]
>>> all(flag == 0 for (_, _, flag) in items)
False
Note that all(flag == 0 for (_, _, flag) in items) is directly equivalent to all(item[2] == 0 for item in items), it's just a little nicer to read in this case.
And, for the filter example, a list comprehension (of course, you could use a generator expression where appropriate):
>>> [x for x in items if x[2] == 0]
[[1, 2, 0], [1, 2, 0]]
If you want to check at least one element is 0, the better option is to use any() which is more readable:
>>> any(flag == 0 for (_, _, flag) in items)
True
Answer from Gareth Latty on Stack OverflowThe best answer here is to use all(), which is the builtin for this situation. We combine this with a generator expression to produce the result you want cleanly and efficiently. For example:
>>> items = [[1, 2, 0], [1, 2, 0], [1, 2, 0]]
>>> all(flag == 0 for (_, _, flag) in items)
True
>>> items = [[1, 2, 0], [1, 2, 1], [1, 2, 0]]
>>> all(flag == 0 for (_, _, flag) in items)
False
Note that all(flag == 0 for (_, _, flag) in items) is directly equivalent to all(item[2] == 0 for item in items), it's just a little nicer to read in this case.
And, for the filter example, a list comprehension (of course, you could use a generator expression where appropriate):
>>> [x for x in items if x[2] == 0]
[[1, 2, 0], [1, 2, 0]]
If you want to check at least one element is 0, the better option is to use any() which is more readable:
>>> any(flag == 0 for (_, _, flag) in items)
True
If you want to check if any item in the list violates a condition use all:
if all([x[2] == 0 for x in lista]):
# Will run if all elements in the list has x[2] = 0 (use not to invert if necessary)
To remove all elements not matching, use filter
# Will remove all elements where x[2] is 0
listb = filter(lambda x: x[2] != 0, listb)
Using any:
>>> data = [False, False, False]
>>> not any(data)
True
any will return True if there's any truth value in the iterable.
Basically there are two functions that deal with an iterable and return True or False depending on which boolean values elements of the sequence evaluate to.
all(iterable)returns True if all elements of theiterableare considered as true values (likereduce(operator.and_, iterable)).any(iterable)returns True if at least one element of theiterableis a true value (again, using functional stuff,reduce(operator.or_, iterable)).
Using the all function, you can map operator.not_ over your list or just build a new sequence with negated values and check that all the elements of the new sequence are true:
>>> all(not element for element in data)
With the any function, you can check that at least one element is true and then negate the result since you need to return False if there's a true element:
>>> not any(data)
According to De Morgan's law, these two variants will return the same result, but I would prefer the last one (which uses any) because it is shorter, more readable (and can be intuitively understood as "there isn't a true value in data") and more efficient (since you don't build any extra sequences).
Suppose you have a list of numbers, and you want to check if any of the numbers are greater than a certain value, or if all of the numbers are less than a certain value.
That can be done with this simple code:
# Original list lst = [1, 2, 3, 4, 5] # Check if any number is greater than 3 has_greater_than_3 = any(x > 3 for x in lst) # Check if all numbers are less than 5 all_less_than_5 = all(x < 5 for x in lst) # Print the results print(has_greater_than_3) # True print(all_less_than_5) # False
The 'any' function returns True if at least one element meets the condition, and the 'all' function returns True if all elements meet the condition.
- You can just use
x[n_trues:]rather thanx[n_trues:len(x)]. - Your comments don't really say more than the code. And so I'd recommend removing the comments.
- If you want to keep your code documented use docstrings, which can be exported to your documentation via tools like Sphinx.
- As commented by Konrad Rudolph, you can remove the
and not any(should_be_false)as this will always fail if theallfails.
def check_true_then_false(x):
"""Check first n values are True and the rest are False."""
return all(x[:sum(x)])
If you want your code to work with iterators, not just sequences then you can instead use:
def check_true_then_false(it):
"""Check first n values are True and the rest are False."""
it = iter(it)
# Takes advantage of the iterating side effect, where it consumes the iterator.
# This allows `all` to simultaneously checks `it` starts with trues and advances `it`.
return all(it) or not any(it)
For the following two inputs all will result in:
>>> all([True] * n)
True
>>> all([True] * n + [False, ...])
False
However it will mean that it is still [...] as all and any are lazy. Meaning that we just need to check the rest are false. Meaning all slices the iterator for you without you having to. Leaving any with:
>>> any([False] * n)
False
>>> any([False] * n + [True, ...])
True
Basically, you want your list of booleans to be sorted.
Specifically, since True > False, you want your list to be sorted in decreasing order:
def check_true_then_false(booleans):
return booleans == sorted(booleans, reverse=True)
Done!
>>> test_cases = [[True],
... [False],
... [True, False],
... [True, False, False],
... [True, True, True, False],
... [False, True],
... [True, False, True]]
>>>
>>> print([check_true_then_false(test_case) for test_case in test_cases])
[True, True, True, True, True, False, False]
Generally speaking:
all and any are functions that take some iterable and return True, if
- in the case of
all, no values in the iterable are falsy; - in the case of
any, at least one value is truthy.
A value x is falsy iff bool(x) == False.
A value x is truthy iff bool(x) == True.
Any non-boolean elements in the iterable are perfectly acceptable — bool(x) maps, or coerces, any x according to these rules:
0,0.0,None,[],(),[],set(), and other empty collections are mapped toFalse- all other values are mapped to
True.
The docstring for bool uses the terms 'true'/'false' for 'truthy'/'falsy', and True/False for the concrete boolean values.
For example:
if all(x > 0 for x in xs) or any(x > 100 for x in xs):
# if nothing is zero or something is over a hundred …
In your specific code samples:
You’ve slightly misunderstood how these functions work. The following does something completely different from what you thought:
if any(foobars) == big_foobar:
...because any(foobars) would first be evaluated to either True or False, and then that boolean value would be compared to big_foobar, which generally always gives you False (unless big_foobar coincidentally happened to be the same boolean value).
Note: the iterable can be a list, but it can also be a generator or a generator expression (≈ lazily evaluated/generated list), or any other iterator.
What you want instead is:
if any(x == big_foobar for x in foobars):
which basically first constructs an iterable that yields a sequence of booleans—for each item in foobars, it compares the item to the value held by big_foobar, and (lazily) emits the resulting boolean into the resulting sequence of booleans:
tmp = (x == big_foobar for x in foobars)
then any walks over all items in tmp and returns True as soon as it finds the first truthy element. It's as if you did the following:
In [1]: foobars = ['big', 'small', 'medium', 'nice', 'ugly']
In [2]: big_foobar = 'big'
In [3]: any(['big' == big_foobar, 'small' == big_foobar, 'medium' == big_foobar, 'nice' == big_foobar, 'ugly' == big_foobar])
Out[3]: True
Note: As DSM pointed out, any(x == y for x in xs) is equivalent to y in xs but the latter is more readable, quicker to write and runs faster.
Some examples:
In [1]: any(x > 5 for x in range(4))
Out[1]: False
In [2]: all(isinstance(x, int) for x in range(10))
Out[2]: True
In [3]: any(x == 'Erik' for x in ['Erik', 'John', 'Jane', 'Jim'])
Out[3]: True
In [4]: all([True, True, True, False, True])
Out[4]: False
See also: http://docs.python.org/2/library/functions.html#all
For the question in the title:
if a list contains one set of values or another
it might be more natural to use set operations. In other words, instead of
if any(x==playerOne for x in board) or any(x==playerTwo for x in board):
# or
if playerOne in board or playerTwo in board:
use set.issubset (or set.intersection1):
if {playerOne, playerTwo}.issubset(board):
# or
if {playerOne, playerTwo} & set(board):
If playerOne and playerTwo are set/list/tuple of values, then compute their union and test if it's a subset of board:
if {*playerOne,*playerTwo}.issubset(board):
Also if the question is
if every item on the board is either playerOne marker or playerTwo marker
then instead of
if all(x == playerOne or x == playerTwo for x in board):
test set equality:1
if {playerOne, playerTwo} == set(board):
1 You can obviously assign set(board) to some variable beforehand so that you don't have to cast board to a set every time you need to test this condition.
values = map(compare, new_subjects.values())
len([x for x in values if x]) == len(values) - 1
Basically, you filter the list for true values and compare the length of that list to the original to see if it's one less.
If you mean is actually True and not evaluates to True, you can just count them?
>>> L1 = [True]*5
>>> L1
[True, True, True, True, True]
>>> L2 = [True]*5 + [False]*2
>>> L2
[True, True, True, True, True, False, False]
>>> L1.count(False)
0
>>> L2.count(False)
2
>>>
checking for only a single False:
>>> def there_can_be_only_one(L):
... return L.count(False) == 1
...
>>> there_can_be_only_one(L1)
False
>>> there_can_be_only_one(L2)
False
>>> L3 = [ True, True, False ]
>>> there_can_be_only_one(L3)
True
>>>
edit: This actually answer your question better:
>>> def there_must_be_only_one(L):
... return L.count(True) == len(L)-1
...
>>> there_must_be_only_one(L3)
True
>>> there_must_be_only_one(L2)
False
>>> there_must_be_only_one(L1)
False