barrigaj
barrigaj

Reputation: 371

Remove elements of one list from another, while keeping duplicates

Basically what I want is this:

>>> a = ["a","a","b","c","c","c","d","e","f"]
>>> b = ["a","b","c","d","e","f"]
>>> #Do something, something like a - b
>>> result = ["a","c","c"]

Reason I want to do this, I am joining a bunch of lists of preferences and want to find which one is common among a lot of lists. The more times they occur in list a (because more lists have that element) the more weight I put towards that

Upvotes: 0

Views: 352

Answers (3)

Ameer
Ameer

Reputation: 2638

Without using multisets, you could iterate over the elements of b and remove from a. Remove only removes a single instance of the element not all instances of equivalent elements. You could do this in succinctly using map.

result = a[:] #copy a
map(result.remove, b) #remove elements of b from a

Upvotes: 0

Martijn Pieters
Martijn Pieters

Reputation: 1123420

You are looking for multisets, really. Use collections.Counter(), the Python implementation of a multiset:

from collections import Counter

acount = Counter(a)
bcount = Counter(b)
result = list((acount - bcount).elements())

Demo:

>>> from collections import Counter
>>> a = ['a', 'a', 'b', 'c', 'c', 'c', 'd', 'e', 'f']
>>> b = ['a', 'b', 'c', 'd', 'e', 'f']
>>> Counter(a) - Counter(b)
Counter({'c': 2, 'a': 1})
>>> list((Counter(a) - Counter(b)).elements())
['a', 'c', 'c']

You may want to retain the Counter() instances however; but if you need it the Counter.elements() method generates a sequence of elements times their count to produce your desired output again.

Upvotes: 9

Braj Kishore
Braj Kishore

Reputation: 351

All you need to do is iterate over each element of b and remove it from a.

Upvotes: 0

Related Questions