26

据我所知,这不是官方不可能的,但是是否有“技巧”通过切片访问列表的任意非顺序元素?

例如:

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

现在我想能够做到

a,b = L[2,5]

这样a == 20b == 50

除了两个陈述之外的一种方法是愚蠢的,例如:

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

但这根本不适合不规则的时间间隔。

也许使用我想要的索引进行列表理解?

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

我很想知道对于这个常见问题有什么建议。

4

5 回答 5

33

可能与您正在寻找的最接近的是itemgetter(或在此处查找 Python 2 文档):

>>> 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)
于 2013-10-02T01:25:03.450 回答
13

如果你可以使用numpy,你可以这样做:

>>> 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与 非常相似list,只是它支持更多操作,例如数学运算以及我们在这里看到的任意索引选择。

于 2013-10-02T01:18:51.600 回答
10

像这样的东西?

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

用法:

>>> 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)

该函数的工作方式是返回一个生成器对象,该生成器对象可以类似于任何类型的 Python 序列进行迭代。

正如@justhalf 在评论中指出的那样,您的调用语法可以通过定义函数参数的方式进行更改。

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

然后你可以调用这个函数:

select(L, [2, 5])

或您选择的任何列表。

更新:我现在推荐使用operator.itemgetter,除非你真的需要生成器的惰性求值特性。请参阅约翰 Y 的回答

于 2013-10-02T01:42:03.390 回答
9

为了完整起见,原始问题的方法非常简单。如果是一个函数本身,您可能希望将它包装在一个函数L中,或者预先将函数结果分配给一个变量,这样它就不会被重复调用:

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

当然它也适用于字符串......

["ABCDEF"[x] for x in [2,0,1]]
['C', 'A', 'B']
于 2013-10-02T13:59:29.883 回答
1

其他答案都不适用于多维对象切片。恕我直言,这是最通用的解决方案(使用numpy):

numpy.ix_允许您同时在数组的所有维度中选择任意索引。

例如:

>>> 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]])
于 2018-05-25T18:55:01.247 回答