Removing items of on list based on another list

Viewed 73

How to remove items from list lst1 based on list lst2?

lst1 = ['abc__2','def__3','xyz__3','pqr__1']
lst2 = ['def','xyz','tuv']

for splitting I did

lst3 = [k.split("__")[0] for k in lst1]

for removing I did

new_list = [i for i in lst3 if i not in lst2]

But in this way, I lost the originality of the original list.

Required list: new_list = ['abc__2','pqr__1']

4 Answers

Instead of creating arr3 with the splited values you can split them in the if when creating new_arr

arr1 = ['abc__2', 'def__3', 'xyz__3', 'pqr__1']
arr2 = ['def', 'xyz', 'tuv']
new_arr = [i for i in arr1 if i.split("__")[0] not in arr2]
print(new_arr) # ['abc__2', 'pqr__1']

We can use an re.search regex approach here to examine each item in the first array, with the help of an alternation:

arr1 = ['abc__2','def__3','xyz__3','pqr__1']
arr2 = ['def','xyz','tuv']
regex = r'^(?:' + r'|'.join(arr2) + r')'

output = [x for x in arr1 if not re.search(regex, x)]
print(output)  # ['abc__2', 'pqr__1']

By the way, the regex pattern being used here is:

^(?:def|xyz|tuv)

Turn arr2 into a set for fast lookup:

s2 = set(arr2)

Then filter based on containment similarly to what you attempted, but without creating the additional list:

[x for x in arr1 if x.split('___')[0] not in s2]

To use the intermediary list arr3, you would have to keep it to the original somehow. One way would be indices:

[arr[i] for i, x in enumerate(arr3) if x not in s2]

Another is to make arr3 into a dictionary instead of a list:

d3 = {x: x.split('___')[0] for x in arr}
[v for k, v in d3.items() if k not in s2]

You could do like this:

arr1 = ['abc__2', 'def__3', 'xyz__3', 'pqr__1']
arr2 = ['def', 'xyz', 'tuv']

new_arr = arr1.copy() #New copy of the arr1
for item in arr1:
    for item2 in arr2:
        if item.startswith(item2):
            new_arr.remove(item)

print(arr1)
print(arr2)
print(new_arr)

Output:

['abc__2', 'def__3', 'xyz__3', 'pqr__1']
['def', 'xyz', 'tuv']
['abc__2', 'pqr__1']
Related