Python切片列表中的第一个和最后一个元素

cho*_*own 60 python list slice subscript

有没有办法只切片列表中的第一个和最后一个项目?

例如; 如果这是我的清单:

>>> some_list
['1', 'B', '3', 'D', '5', 'F']
Run Code Online (Sandbox Code Playgroud)

这样做(显然[0,-1]是无效的语法):

>>> first_item, last_item = some_list[0,-1]
>>> print first_item
'1'
>>> print last_item
'F'
Run Code Online (Sandbox Code Playgroud)

我试过的一些事情:

In [3]: some_list[::-1]
Out[3]: ['F', '5', 'D', '3', 'B', '1']

In [4]: some_list[-1:1:-1]
Out[4]: ['F', '5', 'D', '3']

In [5]: some_list[0:-1:-1]
Out[5]: []
...
Run Code Online (Sandbox Code Playgroud)

mgi*_*son 87

单程:

some_list[::len(some_list)-1]
Run Code Online (Sandbox Code Playgroud)

更好的方法(不使用切片,但更容易阅读):

[some_list[0], some_list[-1]]
Run Code Online (Sandbox Code Playgroud)

  • 第二种形式*更具可读性.明显比隐含更好. (17认同)
  • 因此,"可能是更好的方式".我没有把它放在第一位的唯一原因是因为问题明确要求"切片"而第二种形式在技术上并不是一个切片...... (3认同)
  • 如果 some_list 中只有一项,则切片形式会失败并显示“ValueError:切片步长不能为零” (3认同)
  • 教育OP关于他的方式的愚蠢行为永远不会太晚.:-P (2认同)

jte*_*ace 14

我以为我会用numpy的花式索引来展示如何做到这一点:

>>> import numpy
>>> some_list = ['1', 'B', '3', 'D', '5', 'F']
>>> numpy.array(some_list)[[0,-1]]
array(['1', 'F'], 
      dtype='|S1')
Run Code Online (Sandbox Code Playgroud)

请注意,它还支持任意索引位置,该[::len(some_list)-1]方法不适用于:

>>> numpy.array(some_list)[[0,2,-1]]
array(['1', '3', 'F'], 
      dtype='|S1')
Run Code Online (Sandbox Code Playgroud)

正如DSM指出的那样,你可以使用itemgetter做类似的事情:

>>> import operator
>>> operator.itemgetter(0, 2, -1)(some_list)
('1', '3', 'F')
Run Code Online (Sandbox Code Playgroud)

  • 你可以使用`itemgetter`而不是'numpy`来获得这个变种:`itemgetter(0,-1)(some_list)`. (3认同)

Kat*_*iel 10

first, last = some_list[0], some_list[-1]
Run Code Online (Sandbox Code Playgroud)


cro*_*bc1 7

似乎有些人正在回答错误的问题.你说你想做的事情:

>>> first_item, last_item = some_list[0,-1]
>>> print first_item
'1'
>>> print last_item
'F'
Run Code Online (Sandbox Code Playgroud)

也就是说,您希望将每个元素中的第一个和最后一个元素提取为单独的变量.

在这种情况下,Matthew Adams,pemistahl和katrielalex的答案都是有效的.这只是一个复合作业:

first_item, last_item = some_list[0], some_list[-1]
Run Code Online (Sandbox Code Playgroud)

但是后来你说了一个复杂的问题:"我把它分成同一行,那就要把时间分成两次:"

x, y = a.split("-")[0], a.split("-")[-1]
Run Code Online (Sandbox Code Playgroud)

因此,为了避免两次split()调用,您必须仅对拆分一次所产生的列表进行操作.

在这种情况下,试图在一行中做太多是对清晰度和简单性的损害.使用变量来保存拆分结果:

lst = a.split("-")
first_item, last_item = lst[0], lst[-1]
Run Code Online (Sandbox Code Playgroud)

其他回答回答了"如何获得新列表,包括列表的第一个和最后一个元素?"的问题.他们可能会受到你的头衔的启发,根据你仔细阅读你的问题,它提到你实际上不想要的切片.

AFAIK是使用列表的第0个和最后一个元素获取新列表的3种方法:

>>> s = 'Python ver. 3.4'
>>> a = s.split()
>>> a
['Python', 'ver.', '3.4']

>>> [ a[0], a[-1] ]        # mentioned above
['Python', '3.4']

>>> a[::len(a)-1]          # also mentioned above
['Python', '3.4']

>>> [ a[e] for e in (0,-1) ] # list comprehension, nobody mentioned?
['Python', '3.4']

# Or, if you insist on doing it in one line:
>>> [ s.split()[e] for e in (0,-1) ]
['Python', '3.4']
Run Code Online (Sandbox Code Playgroud)

列表推导方法的优点是元组中的索引集可以是任意的并且以编程方式生成.


Sha*_*ger 7

Python 3中唯一的答案(不使用切片或扔掉的剩余部分list,但可能不够好反正)是使用拆包概括获得firstlast从中间分开:

first, *_, last = some_list
Run Code Online (Sandbox Code Playgroud)

选择_“全部”作为论点“其余部分”是任意的;它们将以_通常用作“我不在乎的东西”的代名词的名称存储。

与许多其他解决方案不同,该解决方案将确保序列中至少包含两个元素;如果只有一个(so first并且last将是相同的),它将引发一个异常(ValueError)。

  • 它也是 O(N),而许多其他解决方案都是 O(1)。这是否重要很大程度上取决于应用程序:)。 (6认同)
  • 我很惊讶这没有得到更多的支持。这是迄今为止最优雅的解决方案,并且避免多次引用该列表。非常适合“打开文件 - 获取第一行 - 分割它 - 获取第一个和最后一个元素(这就是我来到这里的原因)。 (4认同)

Ole*_*pin 6

你可以这样做:

some_list[0::len(some_list)-1]
Run Code Online (Sandbox Code Playgroud)


Chi*_*nke 6

你可以使用类似的东西

y[::max(1, len(y)-1)]
Run Code Online (Sandbox Code Playgroud)

如果你真的想使用切片。这样做的优点是它不会给出索引错误,并且也适用于长度为 1 或 0 的列表。


pem*_*ahl 5

那这个呢?

>>> first_element, last_element = some_list[0], some_list[-1]
Run Code Online (Sandbox Code Playgroud)


Sha*_*ger 5

这不是“切片”,但它是一个通用解决方案,不使用显式索引,并且适用于相关序列是匿名的场景(因此您可以在同一行上创建和“切片”,而无需创建两次并索引两次):operator.itemgetter

import operator

# Done once and reused
first_and_last = operator.itemgetter(0, -1)

...

first, last = first_and_last(some_list)
Run Code Online (Sandbox Code Playgroud)

您可以将其内联为(为了from operator import itemgetter在使用时简洁起见):

first, last = itemgetter(0, -1)(some_list)
Run Code Online (Sandbox Code Playgroud)

但如果您要经常重复使用 getter,则可以通过提前创建一次来节省重新创建它的工作(并给它一个有用的、自记录的名称)。

因此,对于您的特定用例,您可以替换:

x, y = a.split("-")[0], a.split("-")[-1]
Run Code Online (Sandbox Code Playgroud)

和:

x, y = itemgetter(0, -1)(a.split("-"))
Run Code Online (Sandbox Code Playgroud)

并且split仅一次,而不将完整的内容存储list在持久名称中以进行len检查或双索引等。

请注意,itemgetter对于多个项目,返回 a tuple,而不是 a list,因此,如果您不只是将其解压为特定名称,并且需要 true list,则必须将调用包装在list构造函数中。