pythonindexing

Accessing non-consecutive elements of a list or string in python


As far as I can tell, this is not officially possible, but is there a "trick" to access arbitrary non-sequential elements of a list by slicing?

For example:

>>> L = range(0,101,10)
>>> L
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]

Now I want to be able to do

a,b = L[2,5]

so that a == 20 and b == 50

One way besides two statements would be something silly like:

a,b = L[2:6:3][:2]

But that doesn't scale at all to irregular intervals.

Maybe with list comprehension using the indices I want?

[L[x] for x in [2,5]]

I would love to know what is recommended for this common problem.


Solution

  • Something like this?

    def select(lst, *indices):
        return (lst[i] for i in indices)
    

    Usage:

    >>> def select(lst, *indices):
    ...     return (lst[i] for i in indices)
    ...
    >>> L = range(0,101,10)
    >>> a, b = select(L, 2, 5)
    >>> a, b
    (20, 50)
    

    The way the function works is by returning a generator object which can be iterated over similarly to any kind of Python sequence.

    Your call syntax can be changed by the way you define the function parameters.

    def select(lst, indices):
        return (lst[i] for i in indices)
    

    And then you could call the function with:

    select(L, [2, 5])
    

    or any list of your choice.

    Update: I now recommend using operator.itemgetter instead unless you really need the lazy evaluation feature of generators. See John Y's answer.