セットのリストがあります:
setlist = [s1,s2,s3...]
s1∩s2∩s3が欲しい...
ペアワイズs1.intersection(s2)
などを行うことでそれを行う関数を書くことができます。
推奨される、より良い、または組み込みの方法はありますか?
セットのリストがあります:
setlist = [s1,s2,s3...]
s1∩s2∩s3が欲しい...
ペアワイズs1.intersection(s2)
などを行うことでそれを行う関数を書くことができます。
推奨される、より良い、または組み込みの方法はありますか?
回答:
Pythonバージョン2.6以降ではset.intersection()
、のように複数の引数を使用できます。
u = set.intersection(s1, s2, s3)
セットがリストにある場合、これは次のように変換されます。
u = set.intersection(*setlist)
set.intersection
は静的メソッドではないことに注意してください。ただし、これは関数表記を使用して、最初のセットとリストの残りの部分の共通部分を適用します。したがって、引数リストが空の場合、これは失敗します。
明らかにset.intersection
ここに欲しいものですが、「これらすべての合計を取る」、「これらすべての積を取る」、「これらすべてのxorを取る」の一般化が必要な場合は、探しているのはreduce
関数:
from operator import and_
from functools import reduce
print(reduce(and_, [{1,2,3},{2,3,4},{3,4,5}])) # = {3}
または
print(reduce((lambda x,y: x&y), [{1,2,3},{2,3,4},{3,4,5}])) # = {3}
Python 2.6以降がない場合は、明示的なforループを作成する方法もあります。
def set_list_intersection(set_list):
if not set_list:
return set()
result = set_list[0]
for s in set_list[1:]:
result &= s
return result
set_list = [set([1, 2]), set([1, 3]), set([1, 4])]
print set_list_intersection(set_list)
# Output: set([1])
あなたも使うことができますreduce
:
set_list = [set([1, 2]), set([1, 3]), set([1, 4])]
print reduce(lambda s1, s2: s1 & s2, set_list)
# Output: set([1])
ただし、Guido自身を含め、多くのPythonプログラマはこれを嫌っています。
約12年前、Pythonはラムダ、reduce()、filter()、map()を取得しました。これは、Lispハッカーがそれを逃して作業パッチを提出したおかげです。しかし、PRの値にもかかわらず、これらの機能はPython 3000から削除する必要があると思います。
だから今はreduce()です。これは実際に私が常に最も嫌っていたものです。+または*を含むいくつかの例を除いて、重要な関数引数を含むreduce()呼び出しを見るたびに、ペンと紙をつかむ必要があるためです。 reduce()が何をすべきかを理解する前に、その関数に実際に供給されているものを図に示します。したがって、私の考えでは、reduce()の適用範囲は結合演算子にかなり限定されており、他のすべての場合では、累算ループを明示的に記述する方が適切です。
result
が空のときにループを中断することで最適化できることに注意してください。
ここで私は、利用可能な最良の方法を利用しようとする複数の集合交差のための一般的な関数を提供しています:
def multiple_set_intersection(*sets):
"""Return multiple set intersection."""
try:
return set.intersection(*sets)
except TypeError: # this is Python < 2.6 or no arguments
pass
try: a_set= sets[0]
except IndexError: # no arguments
return set() # return empty set
return reduce(a_set.intersection, sets[1:])
グイドは嫌いかもしれませんreduce
が、私はそれが少し好きです:)
sets
にアクセスsets[0]
してキャッチする代わりに、の長さを確認する必要がありIndexError
ます。
a_set
最終戻り時に使用されます。
return reduce(sets[0], sets[1:]) if sets else set()
?
try
/に依存except
することはできる限り避けなければならないため、コードを変更する必要があります。これはコードのにおいであり、非効率的で、他の問題を隠すことができます。
reduce
は「連想演算子に限定されている」と言っていることに注意してください。これは、この場合に適用されます。reduce
多くの場合、理解するのは難しいです&
が、それほど悪くはありません。