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.

Tags:

Python

Numpy