Python List Slicing with Arbitrary Indices

Question:

Is there a better way to extract arbitrary indices from a list in python?

The method I currently use is:

a = range(100)
s = [a[i] for i in [5,13,25]]

Where a is the array I want to slice, and [5,13,25] are the elements that I want to get. It seems much more verbose than the Matlab equivalent:

a = 0:99;
s = a([6,14,26])
Asked By: Ben Hamner

||

Answers:

There is no "ready made" way – the way you do it is quite ingenious, and you could use it.
If you have a lot of that trough your code, you might want to use a subclass of list that would use a syntax just like matlabs – it can be done in a few lines code, the major burden is that you’d have to work always use this new class instead of the built-in lists.

class MyList(list):
    def __getitem__(self, index):
        if not isinstance(index, tuple):
            return list.__getitem__(self, index)
        return [self[i] for i in index]

And on the console:

>>> m = MyList(i * 3 for i in range(100))
>>> m[20, 25,60]
[60, 75, 180]
Answered By: jsbueno

It seems like you would do:

    a = list(range(99)) 
    s = [a[5], a[13], a[25]] 

this seems to be almost identical to the matlab version.

Answered By: Joel Cornett

If you are a Matlab user, but want to use Python, check out numpy:

In [37]: import numpy as np

In [38]: a = np.arange(100)

In [39]: s = a[[5,13,25]]

In [40]: s
Out[40]: array([ 5, 13, 25])

Here is a comparison of NumPy and Matlab, and here is a table of common Matlab commands and their equivalents in NumPy.

Answered By: unutbu
>>> from operator import itemgetter
>>> a = range(100)
>>> itemgetter(5,13,25)(a)
(5, 13, 25)
Answered By: John La Rooy

Here is a more robust version of the excellent accepted @John La Rooy answer. It passes the provided doctests. It always returns a list.

def slice_by_index(lst, indexes):
    """Slice list by positional indexes.

    Adapted from https://stackoverflow.com/a/9108109/304209.

    Args:
        lst: list to slice.
        indexes: iterable of 0-based indexes of the list positions to return.

    Returns:
        a new list containing elements of lst on positions specified by indexes.

    >>> slice_by_index([], [])
    []
    >>> slice_by_index([], [0, 1])
    []
    >>> slice_by_index(['a', 'b', 'c'], [])
    []
    >>> slice_by_index(['a', 'b', 'c'], [0, 2])
    ['a', 'c']
    >>> slice_by_index(['a', 'b', 'c'], [0, 1])
    ['a', 'b']
    >>> slice_by_index(['a', 'b', 'c'], [1])
    ['b']
    """
    if not lst or not indexes:
        return []
    slice_ = itemgetter(*indexes)(lst)
    if len(indexes) == 1:
        return [slice_]
    return list(slice_)
Answered By: Dennis Golomazov
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.