Как получить последние элементы списка в Python? - PullRequest
217 голосов
/ 14 марта 2009

Мне нужны последние 9 цифр списка, и я уверен, что есть способ сделать это с помощью нарезки, но, похоже, я не могу его получить. Я могу получить первые 9, как это:

num_list[0:9]

Любая помощь будет великолепна.

Ответы [ 5 ]

394 голосов
/ 14 марта 2009

Для этого вы можете использовать отрицательные целые числа с оператором нарезки. Вот пример использования интерпретатора Python CLI:

>>> a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
>>> a
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
>>> a[-9:]
[4, 5, 6, 7, 8, 9, 10, 11, 12]

важная строка a[-9:]

82 голосов
/ 14 марта 2009

отрицательный индекс будет отсчитываться с конца списка, поэтому:

num_list[-9:]
41 голосов
/ 08 июля 2014

Нарезка

Срез Python - это невероятно быстрая операция, и это удобный способ быстрого доступа к частям ваших данных.

Обозначение фрагмента для получения последних девяти элементов из списка (или любой другой последовательности, поддерживающей его, например строки) будет выглядеть так:

num_list[-9:]

Когда я вижу это, я читаю часть в скобках как «9-й от конца до конца». (На самом деле, я мысленно сокращаю его как «-9, на»)

Пояснение:

Полная запись

sequence[start:stop:step]

Но двоеточие - это то, что говорит Python, что вы даете ему фрагмент, а не обычный индекс. Вот почему идиоматический способ копирования списков в Python 2 -

list_copy = sequence[:]

И очистить их можно с помощью:

del my_list[:]

(Списки получают list.copy и list.clear в Python 3.)

Дайте своим ломтикам описательное имя!

Может оказаться полезным отделить формирование среза от передачи его методу list.__getitem__ ( - это то, что делают квадратные скобки ). Даже если вы не новичок в этом, он делает ваш код более читабельным, чтобы другие, которым, возможно, придется читать ваш код, могли более легко понять, что вы делаете.

Однако вы не можете просто присвоить переменной целые числа, разделенные двоеточиями. Вам нужно использовать объект среза:

last_nine_slice = slice(-9, None)

Второй аргумент, None, является обязательным, поэтому первый аргумент интерпретируется как start аргумент , в противном случае это будет stop аргумент .

Затем вы можете передать объект фрагмента в вашу последовательность:

>>> list(range(100))[last_nine_slice]
[91, 92, 93, 94, 95, 96, 97, 98, 99]

islice

islice из модуля itertools - еще один эффективный способ получить это. islice не принимает отрицательных аргументов, поэтому в идеале ваша итерация имеет специальный метод __reversed__ - какой список имеет - поэтому вы должны сначала передать свой список (или итерируемый с __reversed__) reversed.

>>> from itertools import islice
>>> islice(reversed(range(100)), 0, 9)
<itertools.islice object at 0xffeb87fc>

islice позволяет выполнять ленивую оценку конвейера данных, поэтому для материализации данных передайте их конструктору (например, list):

>>> list(islice(reversed(range(100)), 0, 9))
[99, 98, 97, 96, 95, 94, 93, 92, 91]
38 голосов
/ 15 марта 2009

Последние 9 элементов можно прочитать слева направо, используя numlist [-9:], или справа налево, используя numlist [: - 10: -1], как вы хотите.

>>> a=range(17)
>>> print a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
>>> print a[-9:]
[8, 9, 10, 11, 12, 13, 14, 15, 16]
>>> print a[:-10:-1]
[16, 15, 14, 13, 12, 11, 10, 9, 8]
3 голосов
/ 22 августа 2017

Вот несколько вариантов получения «хвостовых» элементов итерируемого:

С учетом

n = 9
iterable = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Желаемый выход

[2, 3, 4, 5, 6, 7, 8, 9, 10]

код

Мы получаем последний вывод, используя любую из следующих опций:

from collections import deque
import itertools

import more_itertools


# A: Slicing
iterable[-n:]


# B: Implement an itertools recipe
def tail(n, iterable):
    """Return an iterator over the last *n* items of *iterable*.

        >>> t = tail(3, 'ABCDEFG')
        >>> list(t)
        ['E', 'F', 'G']

    """
    return iter(deque(iterable, maxlen=n))
list(tail(n, iterable))


# C: Use an implemented recipe, via more_itertools
list(more_itertools.tail(n, iterable))


# D: islice, via itertools
list(itertools.islice(iterable, len(iterable)-n, None))


# E: Negative islice, via more_itertools
list(more_itertools.islice_extended(iterable, -n, None))

Детали

  • A. Традиционному Python Slicing присущ язык. Эта опция работает с последовательностями , такими как строки, списки и кортежи. Однако этот тип нарезки не работает на итераторах , например iter(iterable).
  • B. itertools рецепт . Он обобщен для работы с любой итерацией и решает проблему итератора в последнем решении. Этот рецепт должен быть реализован вручную, поскольку он официально не включен в модуль itertools.
  • C. Многие рецепты, включая последний инструмент (B), были удобно реализованы в сторонних пакетах. Установка и импорт этих этих библиотек исключает ручную реализацию. Одна из этих библиотек называется more_itertools (устанавливается через > pip install more-itertools); см more_itertools.tail.
  • D. Член библиотеки itertools. Обратите внимание, что itertools.islice не поддерживает отрицательную нарезку .
  • E. В more_itertools реализован еще один инструмент, обобщающий itertools.islice для поддержки отрицательного среза; см more_itertools.islice_extended.

Какой из них я использую?

Это зависит . В большинстве случаев срез (вариант A, как упоминалось в других ответах) является наиболее простым вариантом, поскольку он встроен в язык и поддерживает большинство итерируемых типов. Для более общих итераторов используйте любой из оставшихся вариантов. Обратите внимание, что опции C и E требуют установки сторонней библиотеки, что может оказаться полезным для некоторых пользователей.

...