5

我有两个清单:

X = [True,False]
Y = [True,True]

我正在尝试将 X[0] 与 Y[0] 和 X[1] 与 Y[1] 进行比较。

我试过了

in [7]: X and Y
Out[7]: [True, True]

但我期待的结果是 [True,False]。

我应该做什么?

4

3 回答 3

16

这是使用 的绝佳机会map,因为and可以用内置函数表示:

import operator
X = [True,False]
Y = [True,True]
map(operator.and_, X,Y)
#=> [True, False]

你得到你所做的行为的原因是and对操作数执行操作,就好像它们已bool应用于它们一样。所有非空列表都True在布尔上下文中计算。

至于“列表理解总是更好”这一点:不,不是。等效的列表推导是:

[x and y for x, y in zip(X, Y)]

它必须构建一个中间对象(列表或生成器,取决于 python 版本),并且仍然需要读者知道做什么zip,就像知道的一样map。它也可能稍微慢一些(因为 map + 内置函数很快 - 这一切都发生在 C 层,本质上)。事实上,timeit显示izip更快(见下文),但我真的认为可读性点更重要;如果性能真的很重要,您可能还会看到不同的结果。

>>> timeit.timeit('map(operator.and_, X,Y)', 'import operator; import itertools; import random; X = [random.choice([True,False]) for _ in range(1000)]; Y = [random.choice([True,False]) for _ in range(1000)]', number=10000)
1.0160579681396484
>>> timeit.timeit('[x and y for x, y in zip(X, Y)]', 'import operator; import itertools; import random; X = [random.choice([True,False]) for _ in range(1000)]; Y = [random.choice([True,False]) for _ in range(1000)]', number=10000)
1.3570780754089355
>>> timeit.timeit('[x and y for x, y in itertools.izip(X, Y)]', 'import operator; import itertools; import random; X = [random.choice([True,False]) for _ in range(1000)]; Y = [random.choice([True,False]) for _ in range(1000)]', number=10000)
0.965054988861084

也就是说,如果您需要任意数量的列表,则需要all在列表推导中使用(或直接结合使用izip);andand_在技术上是按位的 and,因此请注意,如果使用bool.

这是一个all版本:

import itertools
map(all,itertools.izip(X,Y,Z))
于 2013-09-16T19:17:03.653 回答
9

所有非空列表都True在布尔上下文中求值,并and求值为它求值的最后一个表达式(Y在这种情况下),这就是你得到结果的原因。你想要这样的东西:

[x and y for x, y in zip(X, Y)]
于 2013-09-16T19:15:41.270 回答
0

假设您有任意一组列表:

A=[True, False, False]
B=[True, True, False]
C=[3,0,0]

现在编写一些看起来有点像itertools.izip但允许添加函数的东西:

def elements(*iterables, **kwds):
    func=kwds.get('func', None)
    iterables=map(iter, iterables)
    while iterables:
        t=tuple(map(next, iterables)) 
        if func is not None:
            yield func(t)
        else:
            yield t 

现在添加将返回逻辑结果的函数F(A[0],B[0],C[0]...)。例如,它们每个都执行描述的功能:

def ands(elements):
    ''' logical 'and' for all the elements'''
    return all(elements)

def ors(elements):
    ''' logical 'or' for all the elements'''
    return any(elements)

def bitand(elements):
    ''' bitwise 'and' for all the elements'''
    return reduce(operator.and_,elements)    

然后只需调用该函数:

print list(elements(A,B,C,func=ands))  
# [True, False, False]

或者为你的具体例子:

print list(elements([True,False],[True,True],func=ands))  
# [True, False]

或者直接使用all

print list(elements([True,False],[True,True],func=all))   
# [True, False]
于 2013-09-16T21:18:59.613 回答