Расширенный срез, который начинается с начала последовательности с отрицательным шагом
Потерпите меня, пока я объясню свой вопрос. Перейдите к жирному заголовку, если вы уже понимаете индексирование расширенного списка фрагментов.
В python вы можете индексировать списки с использованием нотации среза. Вот пример:
>>> A = list(range(10))
>>> A[0:5]
[0, 1, 2, 3, 4]
Вы также можете включить шаг, который действует как "шаг":
>>> A[0:5:2]
[0, 2, 4]
Штраф также может быть отрицательным, что означает, что элементы извлекаются в обратном порядке:
>>> A[5:0:-1]
[5, 4, 3, 2, 1]
Но подождите! Я хотел увидеть [4, 3, 2, 1, 0]
. О, я вижу, мне нужно уменьшить начальные и конечные индексы:
>>> A[4:-1:-1]
[]
Что случилось? Он интерпретирует -1 как находящийся в конце массива, а не в начале. Я знаю, что вы можете достичь этого следующим образом:
>>> A[4::-1]
[4, 3, 2, 1, 0]
Но вы не можете использовать это во всех случаях. Например, в методе, которому были переданы индексы.
Мой вопрос:
Есть ли какой-либо хороший питонический способ использования расширенных срезов с отрицательными шагами и явных начальных и конечных индексов, которые включают первый элемент последовательности?
Это то, к чему я придумал, но кажется неудовлетворительным.
>>> A[0:5][::-1]
[4, 3, 2, 1, 0]
Ответы
Ответ 1
Хорошо, я думаю, что это, вероятно, так хорошо, как я его получу. Спасибо Абгану за то, что он вызвал эту идею. Это зависит от того, что None в срезе обрабатывается так, как если бы это был отсутствующий параметр. Кто-нибудь получил что-то лучше?
def getReversedList(aList, end, start, step):
return aList[end:start if start!=-1 else None:step]
edit: проверьте start==-1
, а не 0
Это все еще не идеально, потому что вы clobbering обычное поведение -1. Кажется, проблема здесь состоит в двух совпадающих определениях того, что должно было случиться. Тот, кто побеждает, убирает в противном случае действительные призывы, ища другое намерение.
Ответ 2
Склонность к изменению семантики start
и stop
может быть подвержена ошибкам. Используйте None
или -(len(a) + 1)
вместо 0
или -1
. Семантика не является произвольной. См. Статью Edsger W. Dijkstra "Почему нумерация должна начинаться с нуля" .
>>> a = range(10)
>>> start, stop, step = 4, None, -1
Или
>>> start, stop, step = 4, -(len(a) + 1), -1
>>> a[start:stop:step]
[4, 3, 2, 1, 0]
или
>>> s = slice(start, stop, step)
>>> a[s]
[4, 3, 2, 1, 0]
Когда s
представляет собой последовательность, отрицательные индексы в s[i:j:k]
обрабатываются специально:
Если i
или j
является отрицательным, индекс относится к концу строки: len(s) + i
или len(s) + j
. Но учтите, что -0
все еще 0
.
поэтому len(range(10)[4:-1:-1]) == 0
, потому что он эквивалентен range(10)[4:9:-1]
.
Ответ 3
[ A[b] for b in range(end,start,stride) ]
Медленнее, однако вы можете использовать отрицательные индексы, поэтому это должно работать:
[ A[b] for b in range(9, -1, -1) ]
Я понимаю, что это не использование срезов, но я думал, что предлагаю решение в любом случае, если использование срезов специально для получения результата не является приоритетом.
Ответ 4
Я считаю, что следующее вас не удовлетворяет:
def getReversedList(aList, end, start, step):
if step < 0 and start == 0:
return aList[end::step]
return aList[end:start:step]
или он?: -)
Ответ 5
Но вы не можете использовать это, если вы сохранение ваших индексов в переменных для Пример.
Это удовлетворительно?
>>> a = range(10)
>>> start = 0
>>> end = 4
>>> a[4:start-1 if start > 0 else None:-1]
[4, 3, 2, 1, 0]
Ответ 6
Как вы говорите, очень немногие люди полностью понимают все, что вы можете сделать с расширенной срезкой, поэтому, если вам действительно не нужна дополнительная производительность, я бы сделал это "очевидным" способом:
rev_subset = reversed(data[start:stop])
Ответ 7
a[4::-1]
Пример:
Python 2.6 (r26:66714, Dec 4 2008, 11:34:15)
[GCC 4.0.1 (Apple Inc. build 5488)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> a = list(range(10))
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a[4:0:-1]
[4, 3, 2, 1]
>>> a[4::-1]
[4, 3, 2, 1, 0]
>>>
Причина в том, что второй термин интерпретируется как "while not index ==". Выход из него - это "пока индекс в диапазоне".
Ответ 8
Я знаю, что это старый вопрос, но если кто-то вроде меня ищет ответы:
>>> A[5-1::-1]
[4, 3, 2, 1, 0]
>>> A[4:1:-1]
[4, 3, 2]
Ответ 9
Вы можете использовать объект slice(start, stop, step)
, который таков, что
s=slice(start, stop, step)
print a[s]
совпадает с
print a[start : stop : step]
и, кроме того, вы можете установить любой из аргументов None
, чтобы ничего не указывать между двоеточиями. Итак, в случае, которое вы даете, вы можете использовать slice(4, None, -1)
.