I have a list of sets:

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

I want s1 ∩ s2 ∩ s3 …

I can write a function to do it by performing a series of pairwise `s1.intersection(s2)`

, etc.

Is there a recommended, better, or built-in way?

Skip to content
# python – Best way to find the intersection of multiple sets?

## The Question :

*308 people think this question is useful*
*The Question Comments :*
## The Answer 1

*509 people think this answer is useful*
## The Answer 2

*74 people think this answer is useful*
## The Answer 3

*26 people think this answer is useful*
## The Answer 4

*12 people think this answer is useful*
## The Answer 5

*1 people think this answer is useful*
## The Answer 6

*1 people think this answer is useful*
## The Answer 7

*0 people think this answer is useful*

2021-01-19

I have a list of sets:

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

I want s1 ∩ s2 ∩ s3 …

I can write a function to do it by performing a series of pairwise `s1.intersection(s2)`

, etc.

Is there a recommended, better, or built-in way?

From Python version 2.6 on you can use multiple arguments to `set.intersection()`

, like

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

If the sets are in a list, this translates to:

u = set.intersection(*setlist)

where `*a_list`

is list expansion

Note that `set.intersection`

is *not* a static method, but this uses the functional notation to apply intersection of the first set with the rest of the list. So if the argument list is empty this will fail.

As of 2.6, `set.intersection`

takes arbitrarily many iterables.

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

Clearly `set.intersection`

is what you want here, but in case you ever need a generalisation of “take the sum of all these”, “take the product of all these”, “take the xor of all these”, what you are looking for is the `reduce`

function:

from operator import and_ from functools import reduce print(reduce(and_, [{1,2,3},{2,3,4},{3,4,5}])) # = {3}

or

print(reduce((lambda x,y: x&y), [{1,2,3},{2,3,4},{3,4,5}])) # = {3}

If you don’t have Python 2.6 or higher, the alternative is to write an explicit for loop:

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

You can also use `reduce`

:

set_list = [set([1, 2]), set([1, 3]), set([1, 4])] print reduce(lambda s1, s2: s1 & s2, set_list) # Output: set([1])

However, many Python programmers dislike it, including Guido himself:

About 12 years ago, Python aquired lambda, reduce(), filter() and map(), courtesy of (I believe) a Lisp hacker who missed them and submitted working patches. But, despite of the PR value, I think these features should be cut from Python 3000.

So now reduce(). This is actually the one I’ve always hated most, because, apart from a few examples involving + or *, almost every time I see a reduce() call with a non-trivial function argument, I need to grab pen and paper to diagram what’s actually being fed into that function before I understand what the reduce() is supposed to do. So in my mind, the applicability of reduce() is pretty much limited to associative operators, and in all other cases it’s better to write out the accumulation loop explicitly.

Here I’m offering a generic function for multiple set intersection trying to take advantage of the best method available:

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 might dislike `reduce`

, but I’m kind of fond of it 🙂

Jean-François Fabre set.intesection(*list_of_sets) answer is definetly the most Pyhtonic and is rightly the accepted answer.

For those that want to use reduce, the following will also work:

`reduce(set.intersection, list_of_sets)`

I believe the simplest thing to do is:

#assuming three sets set1 = {1,2,3,4,5} set2 = {2,3,8,9} set3 = {2,10,11,12} #intersection set4 = set1 & set2 & set3

set4 will be the intersection of set1 , set2, set3 and will contain the value 2.

print(set4) set([2])