Is there a simple way to index all elements of a list (or array, or whatever) except for a particular index? E.g.,
mylist[3]
I'm going to provide a functional (immutable) way of doing it.
The standard and easy way of doing it is to use slicing:
index_to_remove = 3
data = [*range(5)]
new_data = data[:index_to_remove] + data[index_to_remove + 1:]
print(f"data: {data}, new_data: {new_data}")
Output:
data: [0, 1, 2, 3, 4], new_data: [0, 1, 2, 4]
Use list comprehension:
data = [*range(5)]
new_data = [v for i, v in enumerate(data) if i != index_to_remove]
print(f"data: {data}, new_data: {new_data}")
Output:
data: [0, 1, 2, 3, 4], new_data: [0, 1, 2, 4]
Use filter function:
index_to_remove = 3
data = [*range(5)]
new_data = [*filter(lambda i: i != index_to_remove, data)]
Output:
data: [0, 1, 2, 3, 4], new_data: [0, 1, 2, 4]
Using masking. Masking is provided by itertools.compress function in the standard library:
from itertools import compress
index_to_remove = 3
data = [*range(5)]
mask = [1] * len(data)
mask[index_to_remove] = 0
new_data = [*compress(data, mask)]
print(f"data: {data}, mask: {mask}, new_data: {new_data}")
Output:
data: [0, 1, 2, 3, 4], mask: [1, 1, 1, 0, 1], new_data: [0, 1, 2, 4]
Use itertools.filterfalse function from Python standard library
from itertools import filterfalse
index_to_remove = 3
data = [*range(5)]
new_data = [*filterfalse(lambda i: i == index_to_remove, data)]
print(f"data: {data}, new_data: {new_data}")
Output:
data: [0, 1, 2, 3, 4], new_data: [0, 1, 2, 4]
For a list, you could use a list comp. For example, to make b
a copy of a
without the 3rd element:
a = range(10)[::-1] # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
b = [x for i,x in enumerate(a) if i!=3] # [9, 8, 7, 5, 4, 3, 2, 1, 0]
This is very general, and can be used with all iterables, including numpy arrays. If you replace []
with ()
, b
will be an iterator instead of a list.
Or you could do this in-place with pop
:
a = range(10)[::-1] # a = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
a.pop(3) # a = [9, 8, 7, 5, 4, 3, 2, 1, 0]
In numpy you could do this with a boolean indexing:
a = np.arange(9, -1, -1) # a = array([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])
b = a[np.arange(len(a))!=3] # b = array([9, 8, 7, 5, 4, 3, 2, 1, 0])
which will, in general, be much faster than the list comprehension listed above.
Note that if variable is list of lists, some approaches would fail. For example:
v1 = [[range(3)] for x in range(4)]
v2 = v1[:3]+v1[4:] # this fails
v2
For the general case, use
removed_index = 1
v1 = [[range(3)] for x in range(4)]
v2 = [x for i,x in enumerate(v1) if x!=removed_index]
v2