[英]Element-wise 'and' for lists in python?
我有兩個清單:
X = [True,False]
Y = [True,True]
我試圖將X [0]與Y [0]和X [1]與Y [1]進行比較。
我試過了
in [7]: X and Y
Out[7]: [True, True]
但我期待的結果是[真,假]。
我該怎么辦?
這是使用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))
所有非空列表評估為True
在布爾上下文, and
計算到最后表達它評估( Y
在這種情況下),這就是為什么你會得到你的結果。 你想要這樣的東西:
[x and y for x, y in zip(X, Y)]
假設您有任意組列表:
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]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.