85

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

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

>>> some_list
['1', 'B', '3', 'D', '5', 'F']

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

>>> first_item, last_item = some_list[0,-1]
>>> print first_item
'1'
>>> print last_item
'F'

我尝试过的一些事情:

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]: []
...
4

13 回答 13

106

单程:

some_list[::len(some_list)-1]

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

[some_list[0], some_list[-1]]
于 2012-08-31T15:57:07.387 回答
29

Python 3 唯一的答案(不使用切片或丢弃其余部分list,但无论如何可能已经足够好了)是使用解包泛化来获取firstlast分离中间:

first, *_, last = some_list

选择_作为“其余”论点的总括是任意的;它们将存储在_通常用作“我不关心的东西”的替代名称中。

与许多其他解决方案不同,这个解决方案将确保序列中至少有两个元素;如果只有一个(所以firstlast将是相同的),它将引发异常(ValueError)。

于 2017-04-17T12:32:42.830 回答
21

只是想我会展示如何使用 numpy 的精美索引来做到这一点:

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

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

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

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

>>> import operator
>>> operator.itemgetter(0, 2, -1)(some_list)
('1', '3', 'F')
于 2012-08-31T15:59:49.713 回答
16
first, last = some_list[0], some_list[-1]
于 2012-08-31T15:58:48.527 回答
9

似乎有些人回答错了问题。你说你想做:

>>> first_item, last_item = some_list[0,-1]
>>> print first_item
'1'
>>> print last_item
'F'

即,您想将第一个和最后一个元素分别提取到单独的变量中。

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

first_item, last_item = some_list[0], some_list[-1]

但后来你陈述了一个复杂的问题:“我将它拆分在同一行,那将不得不花时间将它拆分两次:”

x, y = a.split("-")[0], a.split("-")[-1]

因此,为了避免两次 split() 调用,您只能对拆分一次的列表进行操作。

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

lst = a.split("-")
first_item, last_item = lst[0], lst[-1]

其他回答回答了“如何获得一个由列表的第一个和最后一个元素组成的新列表?”的问题。根据仔细阅读您的问题,他们可能受到您的标题的启发,其中提到了您实际上不想要的切片。

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']

列表理解方法的优点是元组中的索引集可以是任意的并且可以通过编程方式生成。

于 2015-08-29T21:54:31.013 回答
8

那这个呢?

>>> first_element, last_element = some_list[0], some_list[-1]
于 2012-08-31T15:58:19.920 回答
7

你可以这样做:

some_list[0::len(some_list)-1]
于 2012-08-31T15:56:55.997 回答
5

你可以使用类似的东西

y[::max(1, len(y)-1)]

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

于 2015-11-03T10:08:33.510 回答
4

其实我只是想通了:

In [20]: some_list[::len(some_list) - 1]
Out[20]: ['1', 'F']
于 2012-08-31T15:57:13.227 回答
4

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

import operator

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

...

first, last = first_and_last(some_list)

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

first, last = itemgetter(0, -1)(some_list)

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

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

x, y = a.split("-")[0], a.split("-")[-1]

和:

x, y = itemgetter(0, -1)(a.split("-"))

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

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

于 2017-04-17T12:18:03.357 回答
3

这个怎么样?

some_list[:1] + some_list[-1:]

Result: ['1', 'F']
于 2021-06-18T16:02:15.950 回答
2

更一般的情况:从列表的每一端返回 N 个点

答案适用于特定的第一个和最后一个,但是像我这样的一些人可能正在寻找一种可以应用于更一般情况的解决方案,在这种情况下,您可以从列表的任一侧返回前 N 个点(假设您有一个排序列表,只想要 5 个最高或最低的),我想出了以下解决方案:

In [1]
def GetWings(inlist,winglen):
    if len(inlist)<=winglen*2:
        outlist=inlist
    else:
        outlist=list(inlist[:winglen])
        outlist.extend(list(inlist[-winglen:]))
    return outlist

以及从列表 1-10 返回底部和顶部 3 个数字的示例:

In [2]
GetWings([1,2,3,4,5,6,7,8,9,10],3)

#Out[2]
#[1, 2, 3, 8, 9, 10]
于 2017-04-28T14:49:08.957 回答
0

有趣的新方法来“单衬”匿名split事物的情况,这样您就不会将其拆分两次,而是在一行中完成所有工作是使用海象运算符 ,:=将赋值作为表达式,允许两者:

first, last = (split_str := a.split("-"))[0], split_str[-1]

和:

first, last = (split_str := a.split("-"))[::len(split_str)-1]

请注意,在这两种情况下,它基本上完全等同于在一行上做:

split_str = a.split("-")

然后跟进以下之一:

first, last = split_str[0], split_str[-1]
first, last = split_str[::len(split_str)-1]

split_str包括在使用和访问它的线路之外仍然存在的事实。它只是在技术上满足单衬的要求,同时相当丑陋。我永远不会推荐它而不是unpackingitemgetter解决方案,即使单衬是强制性的(排除显式索引或切片命名变量并且必须引用所述命名变量两次的非海象版本)。

于 2020-02-24T20:48:18.327 回答