5

I would like to subtract a list of strings where there are more than one element of the same (so set operations are not useful).

Example:

C = ['A','B','B']
D = ['B']

I would like a way to do so that:

C - D = ['A','B']

Example of what I got so far, but does not give the result I want

[item for item in C if item not in D]
returns: ['A']

Here is a more elaborated example to show what I want:

C = ['A','B', 'A','A','B','B','B','X','B']

D = ['A','B','B','Y']

This is what I want the result to be:

C - D = ['A', 'A', 'B', 'B','B','X']
systrigger
  • 398
  • 3
  • 13
Bjarke
  • 51
  • 1
  • 1
  • 4

4 Answers4

6

Without using any libraries:

output = [x for x in C if not x in D or D.remove(x)]

//output: ['A', 'B']
systrigger
  • 398
  • 3
  • 13
  • 1
    Clever use of the None return from remove() +1 – Alain T. Mar 06 '19 at 01:38
  • 1
    This way seem to change the result somehow -- If I run it more than once it's adding an extra B to the result. Not sure what happens, but something is not doing as I would expect or want. – Bjarke Mar 06 '19 at 01:48
4

Though Alain T.'s way is okay, there is a better way using Counter:

from collections import Counter
C = ['A','B','B']
D = ['B']
result = list((Counter(C) - Counter(D)).elements())
iz_
  • 15,923
  • 3
  • 25
  • 40
  • @jslatane There is a difference, although it doesn't show in this example because the count for every element is one. To show the difference, `list(Counter(a=1, b=2)) == ['a', 'b']` while `list(Counter(a=1, b=2).elements()) == ['a', 'b', 'b']`. – iz_ Dec 01 '21 at 05:34
2

You can use Counter from collections:

from collections import Counter
C_D = [i for v,c in (Counter(C)-Counter(D)).items() for i in v*c] 
Alain T.
  • 40,517
  • 4
  • 31
  • 51
0

You can try this:

C = ['A','B', 'A','A','B','B','B','X','B']
D = ['A','B','B','Y']

res = [ i for i in C ]

for i in D:
  if i in C:
    res.remove(i)

print(res)
Shivam Pandya
  • 251
  • 3
  • 10