Каков наилучший (самый быстрый/самый питонический) способ обратить часть массива на месте?
Например.,
def reverse_loop(l,a,b):
while a < b:
l[a],l[b] = l[b],l[a]
a += 1
b -= 1
теперь после
l = list(range(10))
reverse_loop(l,2,6)
l есть [0, 1, 6, 5, 4, 3, 2, 7, 8, 9] по желанию.
Увы, зацикливание в Python неэффективно, поэтому нужен способ получше, например,
def reverse_slice(l,a,b):
l[a:b+1] = l[b:a-1:-1]
и reverse_slice(l,2,6) восстанавливает l его исходное значение.
Увы, для пограничных случаев это не работает: reverse_slice(l,0,6)
усекает l до [7, 8, 9], потому что l[a:-1:-1] должно быть l[a::-1].
Итак, что такое правильный путь?
@student Мне кажется, что этот вопрос касается массивов numpy, тогда как речь идет о Python lists.
@gmds вы имеете в виду, что он не работает для массива, отличного от numpy?
@student Есть тонкие различия. В частности, нарезка будет работать так же, а метод reversed — нет.
@gmds Я думаю, что ответ принятый в приведенной выше ссылке возвращает ожидаемый результат. a[1:4] = a[1:4][::-1] такое же, как l[a:b] = l[a:b][::-1]
@student Это действительно так, но семантика массивов и lists немного отличается, что проявляется в том, что reversed работает в одном случае, а не в другом. Для меня это достаточно различает два вопроса (см. это); принятый ответ, работающий в обоих случаях, кажется, ни здесь, ни там.






Как насчет этого?
def reverse_slice(l, a, b):
l[a:b] = l[a:b][::-1]
l = list(range(10))
reverse_slice(l, 0, 6) # excludes l[6]
print(l)
Выход:
[5, 4, 3, 2, 1, 0, 6, 7, 8, 9]
Альтернатива со встроенной функцией reversed:
def reverse_func(l, a, b):
l[a:b] = reversed(l[a:b])
В моих тестах нарезка выполняется быстрее, чем при использовании reversed, в 1,2–1,5 раза.
[6::-1] можно записать как [6:None:-1]:
def reverse_slice(l,a,b):
a1 = None if a==0 else a-1
l[a:b+1] = l[b:a1:-1]
In [164]: y=x.copy(); reverse_slice(y,1,6);y
Out[164]: [0, 6, 5, 4, 3, 2, 1, 7, 8, 9]
In [165]: y=x.copy(); reverse_slice(y,0,6);y
Out[165]: [6, 5, 4, 3, 2, 1, 0, 7, 8, 9]
это быстрее, чем повторная нарезка?
l[0:6] = l[0:6][::-1]должно работать. См. также здесь