Search code examples
pythonsetsubsetmultisetmultiplicity

Test if set is a subset, considering the number (multiplicity) of each element in the set


I know I can test if set1 is a subset of set2 with:

{'a','b','c'} <= {'a','b','c','d','e'} # True

But the following is also True:

{'a','a','b','c'} <= {'a','b','c','d','e'} # True

How do I have it consider the number of times an element in the set occurs so that:

{'a','b','c'}     <= {'a','b','c','d','e'}      # True
{'a','a','b','c'} <= {'a','b','c','d','e'}      # False since 'a' is in set1 twice but set2 only once
{'a','a','b','c'} <= {'a','a','b','c','d','e'}  # True because both sets have two 'a' elements

I know I could do something like:

A, B, C = ['a','a','b','c'], ['a','b','c','d','e'], ['a','a','b','c','d','e']
all([A.count(i) == B.count(i) for i in A]) # False
all([A.count(i) == C.count(i) for i in A]) # True

But I was wondering if there was something more succinct like set(A).issubset(B,count=True) or a way to stay from list comprehensions. Thanks!


Solution

  • As @DSM deleted his solution , I will take the opportunity to provide a prototype based on which you can expand

    >>> class Multi_set(Counter):
        def __le__(self, rhs):
            return all(v == rhs[k] for k,v in self.items())
    
    
    >>> Multi_set(['a','b','c']) <= Multi_set(['a','b','c','d','e'])
    True
    >>> Multi_set(['a','a','b','c']) <= Multi_set(['a','b','c','d','e'])
    False
    >>> Multi_set(['a','a','b','c']) <= Multi_set(['a','a','b','c','d','e'])
    True
    >>>