jds
jds

Reputation: 61

remove elements of one list from another list python

Is there a pythonic way to remove elements from one list to another list? (Not removing all duplicates)

For example, given [1, 2, 2, 3, 3, 3] (original list) and [1, 2, 3] (elements to be removed). It will return [2, 3, 3] We can assume that the two given lists are always valid. Elements in the "to be removed" list will be in the original list.

Thanks!

Upvotes: 0

Views: 1305

Answers (3)

Jan Lněnička
Jan Lněnička

Reputation: 11

I don't know what problem are you solving with this operation so not sure if this is applicable, but if you can take the elements you want to remove from the original list (for example get random subsequence from the original list and then subtract it) then pythonic and more efficient way (if you do a lot of this operation) would be to use list of hashable objects instead of a list of integers. That way you can do simply set1 - set2 to achieve the goal:

# Create your own element class
class MyElement:
    def __init__(self, value):
        self.value = value

    def __repr__(self):
        return str(self.value)

    # support for less than operator needed for sorting
    def __lt__(self, other):
        return self.value < other.value


original_list = [1, 2, 2, 3, 3, 3]

# Transform list of integers to list of my own MyElement objects
original_list = [MyElement(element) for element in original_list]

# Create subsequence of the original list
to_be_removed = original_list[1:4]

print(original_list)  # [1, 2, 2, 3, 3, 3]
print(to_be_removed)  # [2, 2, 3]

# Subtract the sets
result = set(original_list) - set(to_be_removed)

# Print sorted result
print(sorted(result))  # [1, 3, 3]

It won't preserve original order! But you can sort it at the end.

Upvotes: 0

Juan Pablo Pisano
Juan Pablo Pisano

Reputation: 127

This shoud work


original  = [1, 2, 2, 3, 3, 3] 
remove = [1, 2, 3] 

for i, x in enumerate(original):
    if x in remove:
        original.pop(i)

print(original)

Upvotes: -1

juanpa.arrivillaga
juanpa.arrivillaga

Reputation: 95873

I would use a counter of the elements to be removed.

So, something like

from collections import Counter 

data = [1, 2, 2, 3, 3, 3]
to_be_removed = [1, 2, 3, 3] # notice the extra 3

counts = Counter(to_be_removed)

new_data = []
for x in data:
    if counts[x]:
        counts[x] -= 1
    else:
        new_data.append(x)

print(new_data)

This solution is linear time / space. If you actually need to modify the list (which is code-smell, IMO), you would require quadratic time

Note, consider if you actually just want a multiset - i.e. you could just be working with counters all along, consider:

>>> Counter(data) - Counter(to_be_removed)
Counter({2: 1, 3: 1})

Upvotes: 3

Related Questions