Обратный срез массива на месте

Каков наилучший (самый быстрый/самый питонический) способ обратить часть массива на месте?

Например.,

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

Итак, что такое правильный путь?

l[0:6] = l[0:6][::-1] должно работать. См. также здесь
Cleb 08.04.2019 00:17

@student Мне кажется, что этот вопрос касается массивов numpy, тогда как речь идет о Python lists.

gmds 08.04.2019 00:25

@gmds вы имеете в виду, что он не работает для массива, отличного от numpy?

student 08.04.2019 00:32

@student Есть тонкие различия. В частности, нарезка будет работать так же, а метод reversed — нет.

gmds 08.04.2019 00:38

@gmds Я думаю, что ответ принятый в приведенной выше ссылке возвращает ожидаемый результат. a[1:4] = a[1:4][::-1] такое же, как l[a:b] = l[a:b][::-1]

student 08.04.2019 00:53

@student Это действительно так, но семантика массивов и lists немного отличается, что проявляется в том, что reversed работает в одном случае, а не в другом. Для меня это достаточно различает два вопроса (см. это); принятый ответ, работающий в обоих случаях, кажется, ни здесь, ни там.

gmds 08.04.2019 00:58
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
6
549
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Как насчет этого?

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]

это быстрее, чем повторная нарезка?

sds 08.04.2019 01:18

Другие вопросы по теме

Похожие вопросы