Using any() and all() to check if a list contains one set of values or another

My code is for a Tic Tac Toe game and checking for a draw state but I think this question could be more useful in a general sense.

I have a list that represents the board, it looks like this:

board = [1,2,3,4,5,6,7,8,9]

When a player makes a move the int they moved on is replaced with their marker (‘x’ or ‘o’), I already have checks in place to look for a winning state, what I can’t do is check for a draw state, where none of the list values are ints but a winning state has not been set.

The code I have so far:

if any(board) != playerOne or any(board) != playerTwo:
    print 'continue'
elif all(board) == playerOne or playerTwo:
    print 'Draw'

The if statement works, the elif does not, I think the problem is my ‘or’ operator, what I want to check for is: if the every item on the board is either playerOne marker or playerTwo marker, if I where to make the code:

elif all(board) == playerOne or all(board) == playerTwo:

I would be checking to see if every place on the board was playerOne or every place on the board is playerTwo, which it won’t be.

So how do I check if the board is taken up by a combination of playerOne markers and playerTwo markers?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

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-booleans in the iterable will be fine — bool(x) will map (or coerce, if you prefer) any x according to these rules: 0, 0.0, None, [], (), [], set(), and other empty collections get mapped to False, anything else to True. The docstring for bool uses the terms ‘true’/’false’ for ‘truthy’/’falsy’, and True/False for the concrete boolean values.


In your specific code samples:

You misunderstood a little bit how these functions work. Hence, the following does something completely not 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/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 big_foobar and emits the resulting boolean into the resulting sequence:

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


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x