As far as I can tell, this is not officially not possible, but is there a \"trick\" to access arbitrary non-sequential elements of a list by slicing?
For example:
None of the other answers will work for multidimensional object slicing. IMHO this is the most general solution (uses numpy
):
numpy.ix_ allows you to select arbitrary indices in all dimensions of an array simultaneously.
e.g.:
>>> a = np.arange(10).reshape(2, 5) # create an array
>>> a
array([[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9]])
>>> ixgrid = np.ix_([0, 1], [2, 4]) # create the slice-like grid
>>> ixgrid
(array([[0],
[1]]), array([[2, 4]]))
>>> a[ixgrid] # use the grid to slice a
array([[2, 4],
[7, 9]])
If you can use numpy
, you can do just that:
>>> import numpy
>>> the_list = numpy.array(range(0,101,10))
>>> the_indices = [2,5,7]
>>> the_subset = the_list[the_indices]
>>> print the_subset, type(the_subset)
[20 50 70] <type 'numpy.ndarray'>
>>> print list(the_subset)
[20, 50, 70]
numpy.array is very similar to list
, just that it supports more operation, such as mathematical operations and also arbitrary index selection like we see here.
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.
As @justhalf noted in the comments, 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.
Probably the closest to what you are looking for is itemgetter (or look here for Python 2 docs):
>>> L = list(range(0, 101, 10)) # works in Python 2 or 3
>>> L
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
>>> from operator import itemgetter
>>> itemgetter(2, 5)(L)
(20, 50)
Just for completeness, the method from the original question is pretty simple. You would want to wrap it in a function if L
is a function itself, or assign the function result to a variable beforehand, so it doesn't get called repeatedly:
[L[x] for x in [2,5]]
Of course it would also work for a string...
["ABCDEF"[x] for x in [2,0,1]]
['C', 'A', 'B']