使用 any()和 all()检查列表是否包含一组或另一组值

我的代码是一个井字游戏和检查一个平局状态,但我认为这个问题可能更有用的一般意义上。

我有一个代表董事会的名单,看起来像这样:

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

当一个玩家移动时,他们移动的整型被替换为他们的标记(‘ x’或‘ o’) ,我已经在适当的地方检查寻找一个胜利状态,我不能做的是检查一个平局状态,其中没有列表值是整型的,但一个胜利状态没有被设置。

我目前的代码是:

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

If 语句有效,elif 没有,我认为问题出在我的“或”操作符上,我想检查的是: 如果黑板上的每个项目是 playerOne 标记或 playerTwo 标记,如果我在哪里写代码:

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

我会检查棋盘上的每个地方是否都是2号棋手或者棋盘上的每个地方都是2号棋手,但事实并非如此。

那么我怎么检查黑板是否被一个玩家和两个玩家的组合占据了呢?

215903 次浏览

一般来说:

allany是一些函数,它们采用一些迭代并返回 True,如果

  • all的情况下,迭代中没有值是假的;
  • any的情况下,至少有一个值是真值。

bool(x) == False时,值 x为假。 如果 bool(x) == True,则值 x为真。

迭代中的任何非布尔元素都是完全可以接受的ーー根据以下规则,bool(x)映射或胁迫任何 x:

  • 00.0None[]()[]set()和其他空集合映射到 False
  • 所有其他值都映射到 True

bool的 docstring 使用术语‘ true’/‘ false’表示‘ truthy’/‘ falsy’,True/False表示具体的布尔值。


在您的特定代码示例中:

你可能有点误解了这些函数的工作原理:

if any(foobars) == big_foobar:

... 因为 any(foobars)首先被评估为 TrueFalse,然后这个布尔值将被与 big_foobar进行比较,big_foobar通常总是给你 False(除非 big_foobar碰巧是相同的布尔值)。

注意: 迭代器可以是一个列表,但也可以是一个生成器或生成器表达式(≈延迟计算/生成列表) ,或任何其他迭代器。

相反,你想要的是:

if any(x == big_foobar for x in foobars):

它首先构造一个迭代函数,生成一个布尔值序列ーー对于 foobars中的每个项,它将该项与 big_foobar所持有的值进行比较,然后(惰性地)将生成的布尔值发送到布尔值序列中:

tmp = (x == big_foobar for x in foobars)

然后 any遍历 tmp中的所有项目,一旦找到第一个 true 元素就返回 True。就好像你做了以下事情:

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

注意: 正如 DSM 所指出的,any(x == y for x in xs)等同于 y in xs,但后者更具可读性,写入速度更快,运行速度更快。

一些例子:

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

参见: http://docs.python.org/2/library/functions.html#all