我有两个清单:
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]。
我该怎么办?
答案 0 :(得分:14)
这是使用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 + builtin函数很快 - 它本质上都发生在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
结合使用);并且and_
在技术上是按位的,因此请注意,如果使用bool
以外的数字类型,可能会产生时髦的结果。
以下是all
版本:
import itertools
map(all,itertools.izip(X,Y,Z))
答案 1 :(得分:9)
所有非空列表在布尔上下文中计算为True
,and
计算到它评估的最后一个表达式(在这种情况下为Y
),这就是为什么你得到的结果你这样做。你想要这样的东西:
[x and y for x, y in zip(X, Y)]
答案 2 :(得分: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]