两个布尔列表上的Python AND运算符-怎么样?

问题描述 投票:34回答:9

我有两个布尔列表,例如

x=[True,True,False,False]
y=[True,False,True,False]

我想将这些列表与预期输出一起进行AND:

xy=[True,False,False,False]

我以为表达式x and y可以工作,但是发现它不起作用:实际上,(x and y) != (y and x)

x and y的输出:[True,False,True,False]

y and x的输出:[True,True,False,False]

使用列表理解does具有正确的输出。哇!

xy = [x[i] and y[i] for i in range(len(x)]

请记住,我找不到任何可以告诉我AND运算符的参考,就像我尝试使用x和y一样。但是用Python尝试很容易。有人可以向我解释x and y发生了什么吗?

这是一个简单的测试程序:

import random
random.seed()
n = 10
x = [random.random() > 0.5 for i in range(n)]
y = [random.random() > 0.5 for i in range(n)]
# Next two methods look sensible, but do not work
a = x and y
z = y and x
# Next: apparently only the list comprehension method is correct
xy = [x[i] and y[i] for i in range(n)]
print 'x        : %s'%str(x)
print 'y        : %s'%str(y)
print 'x and y  : %s'%str(a)
print 'y and x  : %s'%str(z)
print '[x and y]: %s'%str(xy)
python list boolean operator-keyword
9个回答
41
投票

and仅根据它们的真实值返回第一个或第二个操作数。如果第一个操作数被认为是假,则返回它,否则返回另一个操作数。

列表为非空时被视为true,因此两个列表均被视为true。他们的内容在这里不起作用

因为两个列表都不为空,所以x and y仅返回第二个列表对象;仅当x为空时,才返回:

>>> [True, False] and ['foo', 'bar']
['foo', 'bar']
>>> [] and ['foo', 'bar']
[]

请参见Python文档中的Truth value testing section

可以测试任何对象的真值,以便在ifwhile条件中使用或用作以下布尔运算的操作数。以下值为假:

[...]

  • 任何空序列,例如''()[]

[...]

所有其他值都被认为是真实的-因此许多类型的对象总是真实的。

(重点是我的,而Boolean operations section在其正下方:

x and y如果x为假,则为x,否则为y

这是一个短路运算符,因此,如果第一个参数为True,它只会计算第二个参数。

您确实需要显式测试列表中的值contained。正如您所发现的,您可以通过列表理解来做到这一点。您可以用zip() function重写它来配对值:

zip()

10
投票

您可以使用numpy:

[a and b for a, b in zip(x, y)]

Numpy允许对数组进行数值和逻辑运算,例如:

>>> import numpy as np
>>> x=np.array([True,True,False,False])
>>> y=np.array([True,False,True,False])
>>> x & y
array([ True, False, False, False], dtype=bool)

您可以使用>>> z=np.array([1,2,3,4]) >>> z+1 array([2, 3, 4, 5]) 运算符按位执行。

代替列表推导,您可以像下面这样使用numpy直接生成布尔数组:

&

4
投票

>>> np.random.random(10)>.5 array([ True, True, True, False, False, True, True, False, False, False], dtype=bool) 不一定是布尔运算符;不管它们的类型如何,它都会返回其两个参数之一。如果第一个参数为假假(and,数字零或空字符串/容器),则它将返回该参数。否则,它返回第二个参数。

在您的情况下,Falsex都是非空列表,因此第一个参数始终为true,这意味着y返回x and yy返回y and x


2
投票

这应该做您想要的:

x

[xy = [a and b for a, b in zip(x, y)] 返回x and yy返回y and x的原因是因为python中的布尔运算符返回了最后一个确定表达式真实性的值。非空x的值为list,并且由于True要求两个操作数都求值为and,因此最后检查的操作数是第二个操作数。与True相对,后者将返回x or y,因为它不需要检查x即可确定表达式的真实性。


1
投票

代替使用

y

一个人可能只是使用numpy来乘以布尔值:

[a and b for a, b in zip(x, y)]

还是我会忽略特殊情况?


0
投票

您可以使用(np.array(x)*np.array(y)) >> array([ True, False, False, False], dtype=bool) 功能

zip

0
投票

除了@Martijn Pieters回答的内容之外,我只需添加以下代码来说明实际使用的x=[True,True,False,False] y=[True,False,True,False] z=[a and b for a,b in zip(x,y)] and操作。

or返回遇到的第一个伪造的值,否则返回最后一个求值的参数。

类似地and返回遇到的第一个真实值,否则返回最后一个求值的参数。

or

值是

nl1 = [3,3,3,3,0,0,0,0] nl2 = [2,2,0,0,2,2,0,0] nl3 = [1,0,1,0,1,0,1,0] and_list = [a and b and c for a,b,c in zip(nl1,nl2,nl3)] or_list = [a or b or c for a,b,c in zip(nl1,nl2,nl3)]

and_list = [1, 0, 0, 0, 0, 0, 0, 0]


0
投票

感谢您的回答@Martijn Pieters和@Tony。我研究了我们必须对两个列表进行“与”运算的各种选择的时间,并且我想分享我的结果,因为我发现它们很有趣。

尽管非常喜欢pythonic方式[zip(x,y)中的a,b的a和b,]却发现确实很慢。我比较了数组(1 *(布尔数组))*(1 *(布尔数组))的整数乘积,结果比原来快10倍以上

or_list = [3, 3, 3, 3, 2, 2, 1, 0]

结果是

import time
import numpy as np
array_to_filter = np.linspace(1,1000000,1000000)                # 1 million of integers :-)
value_limit = 100
cycles = 100

# METHOD #1:  [a and b for a,b in zip(x,y) ]
t0=time.clock()
for jj in range(cycles):
    x = array_to_filter<np.max(array_to_filter)-value_limit   # filter the values > MAX-value_limit
    y = array_to_filter>value_limit                          # filter the values < value_limit
    z= [a and b for a,b in zip(x,y) ]                       # AND
    filtered = array_to_filter[z]
print('METHOD #1 = %.2f s' % ( (time.clock()-t0)))



# METHOD 1*(array of bool) AND  1*(array of bool)
t0=time.clock()
for jj in range(cycles):
    x = 1*(array_to_filter<np.max(array_to_filter)-value_limit)   # filter the values > MAX-value_limit
    y = 1*(array_to_filter>value_limit)                          # filter the values < value_limit
    z = x*y                                                     # AND
    z = z.astype(bool)                                          # convert back to array of bool
    filtered = array_to_filter[z]
print('METHOD #2 = %.2f s' % ( (time.clock()-t0)))

速度几乎受阵列大小或周期数的同等影响。我希望我能帮助某人编码更快。 :-)


0
投票

我相信最简单的解决方案是:

METHOD #1 = 15.36 s
METHOD #2 = 1.85 s
© www.soinside.com 2019 - 2024. All rights reserved.