[python] 여러 세트의 교차점을 찾는 가장 좋은 방법은 무엇입니까?

세트 목록이 있습니다.

setlist = [s1,s2,s3...]

s1 ∩ s2 ∩ s3을 원합니다 …

일련의 pairwise s1.intersection(s2)등 을 수행하여 함수를 작성할 수 있습니다 .

권장되거나, 더 좋거나 내장 된 방법이 있습니까?



답변

Python 버전 2.6부터 다음 set.intersection()과 같이 여러 인수를 사용할 수 있습니다.

u = set.intersection(s1, s2, s3)

세트가 목록에 있으면 다음과 같이 해석됩니다.

u = set.intersection(*setlist)

목록 확장*a_list 은 어디에 있습니까

참고 set.intersection입니다 하지 정적 메서드하지만,이 목록의 나머지 부분과 첫 번째 집합의 교집합을 적용하기 위해 기능 표기법을 사용합니다. 따라서 인수 목록이 비어 있으면 실패합니다.


답변

2.6 set.intersection부터는 반복적으로 많은 iterable이 필요합니다.

>>> 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])

그러나 Guido 자신을 포함하여 많은 Python 프로그래머가 싫어합니다 .

약 12 년 전, 파이썬은 람다, reduce (), filter () 및 map ()을 인수했습니다. 그러나 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있지만, 나는 그것을 좋아합니다. 🙂


답변

장 프랑수아 파 브레 (Jean-François Fabre) set.intesection (* list_of_sets) 답변은 분명히 가장 Pyhtonic이며 정답입니다.

reduce를 사용하려는 사람들에게는 다음도 작동합니다.

reduce(set.intersection, list_of_sets)


답변