两个布尔列表上的 Python AND 运算符 - 如何?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32192163/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 11:11:42  来源:igfitidea点击:

Python AND operator on two boolean lists - how?

pythonlistbooleanoperator-keyword

提问by Glenn N

I have two boolean lists, e.g.,

我有两个布尔列表,例如,

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

I want to AND these lists together, with the expected output:

我想将这些列表与预期的输出结合在一起:

xy=[True,False,False,False]

I thought that expression x and ywould work, but came to discover that it does not: in fact, (x and y) != (y and x)

我以为这种表达x and y会起作用,但后来发现它不起作用:事实上,(x and y) != (y and x)

Output of x and y: [True,False,True,False]

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

Output of y and x: [True,True,False,False]

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

Using list comprehension doeshave correct output. Whew!

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

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

Mind you I could not find any reference that told me the AND operator would work as I tried with x and y. But it's easy to try things in Python. Can someone explain to me what is happening with x and y?

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

And here is a simple test program:

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

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)

采纳答案by Martijn Pieters

andsimply returns either the first or the second operand, based on their truth value. If the first operand is considered false, it is returned, otherwise the other operand is returned.

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

Lists are considered truewhen not empty, so both lists are considered true. Their contents don't play a role here.

列表不为空时被认为是真的,所以两个列表都被认为是真的。它们的内容在这里不起作用

Because both lists are not empty, x and ysimply returns the second list object; only if xwas empty would it be returned instead:

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

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

See the Truth value testingsectionin the Python documentation:

请参阅Python 文档中的真值测试部分

Any object can be tested for truth value, for use in an ifor whilecondition or as operand of the Boolean operations below. The following values are considered false:

[...]

  • any empty sequence, for example, '', (), [].

[...]

All other values are considered true— so objects of many types are always true.

可以测试任何对象的真值,以用于ifwhile条件或作为以下布尔运算的操作数。以下值被认为是错误的:

[...]

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

[...]

所有其他值都被认为是真——所以许多类型的对象总是真。

(emphasis mine), and the Boolean operationssectionright below that:

(强调我的),以及正下方的布尔运算部分

x and y
if xis false, then x, else y

This is a short-circuit operator, so it only evaluates the second argument if the first one is True.

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

这是一个短路运算符,因此它仅在第一个参数为 时才计算第二个参数True

You indeed need to test the values containedin the lists explicitly. You can do so with a list comprehension, as you discovered. You can rewrite it with the zip()functionto pair up the values:

您确实需要明确测试列表中包含的值。正如您发现的那样,您可以使用列表理解来做到这一点。您可以使用zip()函数重写它以配对值:

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

回答by Cyphase

This should do what you want:

这应该做你想做的:

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

The reason x and yreturns yand y and xreturns xis because boolean operators in python return the last value checked that determines the true-ness of the expression. Non-empty list's evaluate to True, and since andrequires both operands to evaluate True, the last operand checked is the second operand. Contrast with x or y, which would return xbecause it doesn't need to check yto determine the true-ness of the expression.

x and y返回yy and x返回的原因x是因为 python 中的布尔运算符返回检查的最后一个值,该值确定表达式的真实性。非空list的求值为True,并且由于and需要两个操作数来求值True,因此检查的最后一个操作数是第二个操作数。与 相比x or y,它将返回,x因为它不需要检查y以确定表达式的真实性。

回答by Uri Goren

You can use the zipfunction

您可以使用该zip功能

x=[True,True,False,False]
y=[True,False,True,False]
z=[a and b for a,b in zip(x,y)]

回答by chepner

andis not necessarily a Boolean operator; it returns one of its two arguments, regardless of their type. If the first argument is false-ish (False, numeric zero, or an empty string/container), it returns that argument. Otherwise, it returns the second argument.

and不一定是布尔运算符;它返回它的两个参数之一,而不管它们的类型。如果第一个参数是 false-ish(False、数字零或空字符串/容器),则返回该参数。否则,它返回第二个参数。

In your case, both xand yare non-empty lists, so the first argument is always true-ish, meaning x and yreturns yand y and xreturns x.

在您的情况下,xy都是非空列表,因此第一个参数始终是 true-ish,意思是x and y返回yy and x返回x

回答by dawg

You could use numpy:

你可以使用 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)

Numpy allows numerical and logical operations on arrays such as:

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

>>> z=np.array([1,2,3,4])
>>> z+1
array([2, 3, 4, 5])

You can perform bitwise and with the &operator.

您可以使用&运算符执行按位和。

Instead of a list comprehension, you can use numpy to generate the boolean array directly like so:

您可以使用 numpy 直接生成布尔数组,而不是列表理解:

>>> np.random.random(10)>.5
array([ True,  True,  True, False, False,  True,  True, False, False, False], dtype=bool)

回答by Philipp

Instead of using

而不是使用

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

one could just use the possibility of numpy to multiply bool-values:

人们可以使用 numpy 的可能性来乘以布尔值:

(np.array(x)*np.array(y))
>> array([ True, False, False, False], dtype=bool)

Or do I overlook a special case?

还是我忽略了一个特殊情况?

回答by Manishankar Singh

In addition to what @Martijn Pieters has answered, I would just add the following code to explain andand oroperations in action.

除了@Martijn Pieters 所回答的内容之外,我只想添加以下代码来解释andor操作。

andreturns the first falsy value encountered else the last evaluated argument.

and返回遇到的第一个假值,否则为最后一个评估参数。

Similarly orreturns the first truthy value encountered else the last evaluated argument.

类似地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)]

Values are

值是

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

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

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

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

回答by Marco Triches

Thanks for the answer @Martijn Pieters and @Tony. I dig into the timing of the various options we have to make the AND of two lists and I would like to share my results, because I found them interesting.

感谢@Martijn Pieters 和@Tony 的回答。我深入研究了我们必须对两个列表进行 AND 的各种选项的时间安排,我想分享我的结果,因为我发现它们很有趣。

Despite liking a lot the pythonic way [a and b for a,b in zip(x,y) ], turns out really slow. I compare with a integer product of arrays (1*(array of bool)) * (1*(array of bool)) and it turns out to be more than 10x faster

尽管非常喜欢pythonic方式[a和b for a,b in zip(x,y)],结果真的很慢。我与数组的整数乘积 (1*(array of bool)) * (1*(array of bool)) 进行比较,结果证明快 10 倍以上

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)))

The results are

结果是

METHOD #1 = 15.36 s
METHOD #2 = 1.85 s

The speed is almost affected equally by the size of the array or by the number of cycles.
I hope I helped someone code to be faster. :-)

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

回答by AlwaysLearning

Here is a simple solution:

这是一个简单的解决方案:

np.logical_and(x,y)