可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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:
>>> 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.
回答1:
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.
回答2:
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)
回答3:
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.
回答4:
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']
回答5:
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]])