109

Is there a fast way to check if one set entirely contains another?

Something like:

>>>[1, 2, 3].containsAll([2, 1])
True

>>>[1, 2, 3].containsAll([3, 5, 9])
False
SilentGhost
  • 307,395
  • 66
  • 306
  • 293
Nick Heiner
  • 119,074
  • 188
  • 476
  • 699
  • For "multiset" see [python - How to check if all items in a list are there in another list? - Stack Overflow](https://stackoverflow.com/questions/15147751/how-to-check-if-all-items-in-a-list-are-there-in-another-list) . – user202729 Dec 05 '21 at 17:53

7 Answers7

162

Those are lists, but if you really mean sets you can use the issubset method.

>>> s = set([1,2,3])
>>> t = set([1,2])
>>> t.issubset(s)
True
>>> s.issuperset(t)
True

For a list, you will not be able to do better than checking each element.

Aelius
  • 1,029
  • 11
  • 22
danben
  • 80,905
  • 18
  • 123
  • 145
42

For completeness: this is equivalent to issubset (although arguably a bit less explicit/readable):

>>> set([1,2,3]) >= set([2,1])
True
>>> set([1,2,3]) >= set([3,5,9])
False
ChristopheD
  • 112,638
  • 29
  • 165
  • 179
8

You can use either set.issubset() or set.issuperset() (or their operator based counterparts: <= and >=). Note that the methods will accept any iterable as an argument, not just a set:

>>> {1, 2}.issubset([1, 2, 3])
True
>>> {1, 2, 3}.issuperset([1, 2])
True

However, if you use operators, both arguments must be sets:

>>> {1, 2} <= {1, 2, 3}
True
>>> {1, 2, 3} >= {1, 2}
True
Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
6

If you suspect a set to be a subset of another, and intersect those two sets together, the result is equal to itself if it is a subset.

a = [2,1,3,3]
b = [5,4,3,2,1]
set(a).intersection(set(b)) == set(a)
>>True
Jordan Stefanelli
  • 1,446
  • 1
  • 13
  • 13
  • 2
    Let `A = set(a)` and `B = set(b)` for sanity. Then this comparison is efficiently reducible to `len(A.intersection(B)) == len(A)`. That is, the sets themselves need *not* be compared element-wise; only the cardinality of these sets need be compared. Even this optimization is probably insufficient to render this approach preferable, however. The dramatically more readable *and* efficient `issubset()` and `<=` approaches are almost certainly what everyone want. – Cecil Curry Feb 09 '18 at 05:57
  • @CecilCurry True - I used the word 'cardinality' incorrectly as it is a length measurement. I've updated the wording. Your optimization is an error based on my error. Not an optimization. The literal wording of "intersection()" reads more explicit than the overloaded implications of ">=" and stating that "issubset()" is easier to read is kind of an elimination of the obvious since it is the most popular answer. Feel free to contribute a creative solution beyond repeating others' answers. – Jordan Stefanelli Jul 04 '19 at 16:11
5

One option is left untouched -- subtraction:

>>> {1, 2} - {1, 2, 3}
set([])
>>> {1, 2, 3} - {1, 2}
set([3])

Basically you check what elements in first list are not in second list.

I found it very handy since you could show what values are missing:

>>> def check_contains(a, b):
...     diff = a - b
...     if not diff:
...         # All elements from a are present in b
...         return True
...     print('Some elements are missing: {}'.format(diff))
...     return False
...
>>> check_contains({1, 2}, {1, 2, 3})
True
>>> check_contains({1, 2, 3}, {1, 2})
Some elements are missing: set([3])
False
Artem Skoretskiy
  • 878
  • 10
  • 9
2
>>> set([1,2,3]).issuperset(set([2,1]))
True
>>> set([1,2,3]).issuperset(set([3,5,9]))
False
Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
Mamata
  • 21
  • 1
0

Below function return 0 if mainlist doesn't contains sublist fully and 1 if contains fully.

def islistsubset(sublist,mainlist):
     for item in sublist:
             if item in mainlist:
                     contains = 1
             else:
                     contains = 0
                     break;
     return contains
  • 2
    This is O(n^2) while using set operations as in some of the existing answers is much faster. This can also be written simply `any(item in mainlist for item in sublist)`. – Iguananaut Oct 25 '17 at 12:09
  • Agree infact I could also write def islistsubset(sublist,mainlist): contains = 1 for item in sublist: if item in mainlist: continue else: contains = 0 break; return contains So only 2 assignments per call – Bobin Motti Thomas Oct 26 '17 at 13:04
  • 1
    @BobinMottiThomas You can just directly return True or False without creating any temporary variable. for item in list_a: if item not in list_b: return False return True – Jordan Stefanelli Oct 26 '17 at 15:17