セットのリストがあります:
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)
ここで*a_list
は リスト展開 です
2.6の時点で、set.intersection
は任意の数の反復可能オブジェクトを取ります。
>>> s1 = set([1, 2, 3])
>>> s2 = set([2, 3, 4])
>>> s3 = set([2, 4, 6])
>>> s1 & s2 & s3
set([2])
>>> s1.intersection(s2, s3)
set([2])
>>> sets = [s1, s2, s3]
>>> set.intersection(*sets)
set([2])
明らかに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])
しかし、多くのPythonプログラマーはそれを嫌います Guido自身を含む :
約12年前、Pythonはラムダ、reduce()、filter()、map()を取得しました。それらを逃し、動作中のパッチを提出したLISPハッカーのおかげです(私は信じています)。しかし、PR値にもかかわらず、これらの機能はPython 3000からカットされるべきだと思います。
だから今reduce()。これは、実際に私が常に最も嫌っていたものです。なぜなら、+または*を含むいくつかの例は別として、非自明な関数引数を持つreduce()呼び出しを見るたびに、ペンと紙をつかむ必要があるからです。 reduce()が何をすべきかを理解する前に、実際にその関数に何が送られているかを図で示します。したがって、私の考えでは、reduce()の適用可能性は連想演算子にほぼ限定されており、他のすべての場合では、累積ループを明示的に書き出す方が適切です。
ここでは、利用可能な最善の方法を活用しようとする複数集合交差の汎用関数を提供しています。
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:])
Guidoはreduce
を嫌うかもしれませんが、私はそれが好きです:)