私は2つのリストを持っています:
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] でした。
私は何をすべきですか?
私は2つのリストを持っています:
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] でした。
私は何をすべきですか?
は組み込み関数で表すことができる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))
空でないすべてのリスト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]