Some style issues:
- Function names should be snake_case, not PascalCase.
- Function arguments should be lower case.
- The operators need more space.
- There's no documentation comment to explain what the function does, or to show examples.
This looks like it could be greatly simplified using the Standard Library's collections.Counter
:
Here's how you would use Counter
to perform the same operation, complete with unit tests:
from collections import Counter
def subtract_multiset(a, b):
'''
Return a copy of a with the elements of b removed.
>>> subtract_multiset([], [0, 1])
[]
>>> subtract_multiset(["x", "x", "y"], [])
['x', 'x', 'y']
>>> subtract_multiset(["ham", "spam", "eggs", "spam", "spam"], ["spam", "spam"])
['ham', 'spam', 'eggs']
>>> subtract_multiset([0, 0, 1, 1], [0, 1, 1, 1])
[0]
>>> subtract_multiset([1, 2, 2, 3], [1, 2, 3, 4])
[2]
'''
diff = Counter(a) - Counter(b)
return list(diff.elements())
if __name__ == '__main__':
import doctest
doctest.testmod()
This scales better as we increase the length of the lists:
The question code calls list.count()
on both A
and B
inside the loop, which executes for every element in the set r1
. So it scales as O(N²) where N is the total number of elements, assuming the number of unique elements in A
is proportional to the size of A
.
Constructing the counters looks at each element once, with a log N
lookup (pretty similar to constructing the set
in the original implementation). But after that, the counter subtraction and listing of elements has smaller impact, so overall performance tends to O(N log N).
4
, since that digit is only present in the second set. \$\endgroup\$