在python中访问列表或字符串的非连续元素

ber*_*roe 21 python string indexing list slice

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

例如:

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

现在我希望能够做到

a,b = L[2,5]
Run Code Online (Sandbox Code Playgroud)

这样a == 20b == 50

除了两个陈述之外的一种方式是愚蠢的:

a,b = L[2:6:3][:2]
Run Code Online (Sandbox Code Playgroud)

但这根本不会按不规则的间隔进行扩展.

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

[L[x] for x in [2,5]]
Run Code Online (Sandbox Code Playgroud)

我很想知道这个常见问题的推荐方法.

Joh*_*n Y 26

可能最接近您正在寻找的是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)
Run Code Online (Sandbox Code Playgroud)

  • @beroe:在你接受了另一个答案之后,它仍然会得到更多*新*票*,所以早些时候与它无关.我相信我的答案是获得更多选票的原因是经验丰富的Python程序员通常更喜欢使用`itemgetter`而不是定义新函数.一次导入比一个函数定义更简单,更简单. (4认同)
  • @justhalf:嗯,`itemgetter`与Shashank的答案非常相似,除了已经包含在Python标准库中. (2认同)

jus*_*alf 11

如果你可以使用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]
Run Code Online (Sandbox Code Playgroud)

numpy.array非常相似list,只是它支持更多的操作,如数学运算和任意索引选择,就像我们在这里看到的那样.

  • 这应该是我认为可接受的答案. (3认同)
  • 我认为它不是公认的答案的原因是因为(a)它有更多膨胀,(b)它不那么普遍.(a):`numpy`是一个**巨大的**库,这个答案将整个内容拉进去.(也许是来自numpy import array`?)(b):`numpy`是*具体*用于数学运算,因此,那些专注于后端网络开发的人们不那么熟悉.`itemgetter`更接近"裸"的Python,可以覆盖更广泛的受众. (2认同)
  • 我相信,“from numpy import array”仍会加载整个 numpy 包。但你是对的,如果列表不用于数学运算,这可能有点矫枉过正。 (2认同)

Sha*_*ank 9

像这样的东西?

def select(lst, *indices):
    return (lst[i] for i in indices)
Run Code Online (Sandbox Code Playgroud)

用法:

>>> 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)
Run Code Online (Sandbox Code Playgroud)

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

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

def select(lst, indices):
    return (lst[i] for i in indices)
Run Code Online (Sandbox Code Playgroud)

然后你可以调用函数:

select(L, [2, 5])
Run Code Online (Sandbox Code Playgroud)

或任何您选择的清单.

更新:我现在建议使用,operator.itemgetter除非你真的需要生成器的惰性评估功能.请参阅John Y的回答.


ber*_*roe 8

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

[L[x] for x in [2,5]]
Run Code Online (Sandbox Code Playgroud)

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

["ABCDEF"[x] for x in [2,0,1]]
['C', 'A', 'B']
Run Code Online (Sandbox Code Playgroud)