How do you 'remove' a numpy array from a list of numpy arrays?
Here you go:
list.pop(1)
Update:
list.pop(list.index(element))
I don't think you can get around traversing the list to find the position of the element. Don't worry about it. Python will, by default use a good searching algorithm to find it at least cost for you.
Use Python Basic Functionalities
The following solution uses the list.index(element)
method from the
list of arrays.
Searching for a numpy.ndarray
needs to be able to hash numpy.ndarray instances. Therefore, we need to implement
a hashing algorithm. This is fairly simple, although the code presented looks a bit long, most of the lines are used for checking for edge cases or the addition of comments.
You can copy paste the code into a file and run it from the command line or a SDK as PyCharm.
You need to know about
- [].index(element)
- hash (hashing and hash collisions)
- how to hash a numpy array
Note:
- hash collisions can lead to wrong decisions, you need to decide yourself about the probability and impact
- only the first occurence of the array is removed, should there be several with the same data.
import numpy as np
def remove(array, arrays):
"""
Remove the `array` from the `list` of `arrays`
Operates inplace on the `list` of `arrays` given
:param array: `np.ndarray`
:param arrays: `list:np.ndarray`
:return: None
"""
assert isinstance(arrays, list), f'Expected a list, got {type(arrays)} instead'
assert isinstance(array, np.ndarray), f'Expected a numpy.ndarray, got {type(array)} instead'
for a in arrays:
assert isinstance(a, np.ndarray), f'Expected a numpy.ndarray instances in arrays, found {type(a)} instead'
# Numpy ndarrays are not hashable by default, so we create
# our own hashing algorithm. The following will do the job ...
def _hash(a):
return hash(a.tobytes())
try:
# We create a list of hashes and search for the index
# of the hash of the array we want to remove.
index = [_hash(a) for a in arrays].index(_hash(array))
except ValueError as e:
# It might be, that the array is not in the list at all.
print(f'Array not in list. Leaving input unchanged.')
else:
# Only in the case of no exception we pop the array
# with the same index/position from the original
# arrays list
arrays.pop(index)
if __name__ == '__main__':
# Let's start with the following arrays as given in the question
arrays = [np.array([1, 1, 1]), np.array([2, 2, 2]), np.array([3, 3, 3])]
print(arrays)
# And remove this array instance from it.
# Note, this is a new instance, so the object id is
# different. Structure and values coincide.
remove(np.array([2, 2, 2]), arrays)
# Let's check the result
print(arrays)
# Let's check, whether our edge case handling works.
remove(np.array([1, 2, 3]), arrays)
The problem here is that when two numpy arrays are compared with ==, as in the remove() and index() methods, a numpy array of boolean values (the element by element comparisons) is returned which is interpretted as being ambiguous. A good way to compare two numpy arrays for equality is to use numpy's array_equal() function.
Since the remove() method of lists doesn't have a key argument (like sort() does), I think that you need to make your own function to do this. Here's one that I made:
def removearray(L,arr):
ind = 0
size = len(L)
while ind != size and not np.array_equal(L[ind],arr):
ind += 1
if ind != size:
L.pop(ind)
else:
raise ValueError('array not found in list.')
If you need it to be faster then you could Cython-ize it.