Matt Matt - 4 months ago 17
Python Question

Python list.remove(x) 2.7.5

I have two lists shown below. I'm trying to use the list.remove(x) function to remove the files that are in both list1 and list2, but one of my lists has file extensions while the other does not! What should be my approach!?

List1 = ['myfile.v', 'myfile2.sv', 'myfile3.vhd', 'etcfile.v', 'randfile.sv']
List2 = ['myfile', 'myfile2', 'myfile3']

#This is in short what I would like to do, but the file extensions throw off
#the tool!
for x in List2:
List1.remove(x)


Thanks!

Answer

It's really dangerous to loop over a list as you are removing items from it. You'll nearly always end up skipping over some elements.

>>> L = [1, 1, 2, 2, 3, 3]
>>> for x in L:
...     print x
...     if x == 2:
...         L.remove(2)
... 
1
1
2
3
3

It's also inefficient, since each .remove is O(n) complexity

Better to create a new list and bind it back to list1

import os
list1 = ['myfile.v', 'myfile2.sv', 'myfile3.vhd', 'etcfile.v', 'randfile.sv']
list2 = ['myfile', 'myfile2', 'myfile3']
set2 = set(list2)  # Use a set for O(1) lookups
list1 = [x for x in list1 if os.path.splitext(x)[0] not in set2]

or for an "inplace" version

list1[:] = [x for x in list1 if os.path.splitext(x)[0] not in set2]

for a truly inplace version as discussed in the comments - doesn't use extra O(n) memory. And runs in O(n) time

>>> list1 = ['myfile.v', 'myfile2.sv', 'myfile3.vhd', 'etcfile.v', 'randfile.sv']
>>> p = 0
>>> for x in list1:
...     if os.path.splitext(x)[0] not in set2:
...         list1[p] = x
...         p += 1
... 
>>> del(list1[p:])
>>> list1
['etcfile.v', 'randfile.sv']