Эффективный способ повернуть список в Python

263

Какой самый эффективный способ повернуть список в Python? Прямо сейчас у меня есть что-то вроде этого:

>>> def rotate(l, n):
...     return l[n:] + l[:n]
... 
>>> l = [1,2,3,4]
>>> rotate(l,1)
[2, 3, 4, 1]
>>> rotate(l,2)
[3, 4, 1, 2]
>>> rotate(l,0)
[1, 2, 3, 4]
>>> rotate(l,-1)
[4, 1, 2, 3]

Есть ли способ лучше?

Джелил
источник
12
Это на самом деле не сдвиг, поскольку другие языки (Perl, Ruby) используют этот термин. Это поворот. Может быть, вопрос должен быть обновлен соответственно?
Винсент Фурмонд
@dzhelil Мне очень нравится ваше оригинальное решение, потому что оно не содержит мутаций
juanchito
2
numpy.roll
BoltzmannBrain
2
Я думаю, что rotateэто правильное слово, а не shift.
Codeforester
2
Реальный правильный ответ, это вы никогда не должны вращаться список в первую очередь. Создайте переменную «указатель» на логическое место в вашем списке, где вы хотите, чтобы были «голова» или «хвост», и измените эту переменную вместо перемещения любого из элементов в списке. Найдите оператор «modulo»% для эффективного способа «обернуть» указатель вокруг начала и конца списка.
CND

Ответы:

280

А collections.dequeоптимизирован для тяги и толкания на обоих концах. У них даже есть специальный rotate()метод.

from collections import deque
items = deque([1, 2])
items.append(3)        # deque == [1, 2, 3]
items.rotate(1)        # The deque is now: [3, 1, 2]
items.rotate(-1)       # Returns deque to original state: [1, 2, 3]
item = items.popleft() # deque == [2, 3]
Игнасио Васкес-Абрамс
источник
8
Для будущих читателей: collections.deque rotate()это быстрее, чем нарезка в соответствии с wiki.python.org/moin/TimeComplexity
Джефф
2
Но имейте deque.rotateв виду , использование требует сначала преобразования типа в dequeобъект, что медленнее, чем l.append(l.pop(0)). Так что если у вас есть объект deque для начала, убедитесь, что он самый быстрый. В противном случае используйте l.append(l.pop(0)).
Purrell
8
Чтобы уточнить, deque.rotateэто O (k), но преобразование типа из списка в deque является O (n) . Поэтому, если вы начнете со списка, использование deque.rotate будет O (n) + O (k) = O (n). l.append(l.pop(0))с другой стороны, O (1).
Purrell
3
@Purrell, передний элемент - O (n). В wiki.python.org/moin/TimeComplexity он указан как O (k), а k - это число элементов в списке, следующих за извлеченным элементом, поскольку структура данных сдвигает все последующие элементы в начало списка. По этой причине за O (1) можно извлечь только последний элемент.
Кирк Бойер
88

Как насчет просто использовать pop(0)?

list.pop([i])

Удалите элемент в указанной позиции в списке и верните его. Если индекс не указан, a.pop()удаляет и возвращает последний элемент в списке. (Квадратные скобки iв сигнатуре метода означают, что параметр является необязательным, а не то, что вы должны вводить квадратные скобки в этой позиции. Вы часто будете видеть эту запись в Справочнике по библиотеке Python.)

Jamgold
источник
16
Но не будет ли стоить O (k) за удаление каждого элемента в списке, где k - количество оставшихся элементов. Таким образом, общее время будет O (n ^ 2) wiki.python.org/moin/TimeComplexity
Pramod
5
Это на самом деле не отвечает на вопрос. Вопрос не в том, чтобы вернуть элементы по порядку, а в том, чтобы создать новый список в другом порядке.
user650261
5
нет, ответ на вопрос с использованием pop будет l.append(l.pop(0). Что, если я не ошибаюсь, является O (1).
Purrell
4
list.pop внутренне вызывает list_ass_slice, который использует memmove для очень быстрого перемещения всех элементов, но все равно O (n). См github.com/python/cpython/blob/master/Objects/listobject.c и wiki.python.org/moin/TimeComplexity . Единственный элемент, который можно удалить из списка Python за постоянное время, - последний.
DRayX
2
Downvoted. Из docs.python.org/3/tutorial/… Также можно использовать список в качестве очереди, где первый добавленный элемент - это первый извлеченный элемент («первым пришел , первым вышел»); однако списки не эффективны для этой цели. Хотя добавления и вставки в конце списка выполняются быстро, вставки или вставки в начале списка выполняются медленно (поскольку все остальные элементы должны быть сдвинуты на единицу).
SantaXL
59

Numpy может сделать это с помощью rollкоманды:

>>> import numpy
>>> a=numpy.arange(1,10) #Generate some data
>>> numpy.roll(a,1)
array([9, 1, 2, 3, 4, 5, 6, 7, 8])
>>> numpy.roll(a,-1)
array([2, 3, 4, 5, 6, 7, 8, 9, 1])
>>> numpy.roll(a,5)
array([5, 6, 7, 8, 9, 1, 2, 3, 4])
>>> numpy.roll(a,9)
array([1, 2, 3, 4, 5, 6, 7, 8, 9])
Ричард
источник
1
Что мне нравится в SO, так это то, что иногда в ленте ответов можно найти новые замечательные сокровища, подобные этому :)
noamgot
Это, когда я проверял это, очень, очень медленно
Питер Харрисон
@PeterHarrison: Поскольку вы не предоставляете подробности тестирования, трудно понять, что вы имеете в виду. Этот ответ содержит полную информацию о тестировании и сравнение сроков.
Ричард
33

Это зависит от того, что вы хотите, чтобы произошло, когда вы делаете это:

>>> shift([1,2,3], 14)

Вы можете изменить свой:

def shift(seq, n):
    return seq[n:]+seq[:n]

чтобы:

def shift(seq, n):
    n = n % len(seq)
    return seq[n:] + seq[:n]
jcdyer
источник
5
Примечание: это приведет к сбою для пустых списков.
meawoppl
n = n% len (seq) return = seq [-n:] + seq [: - n]
user3303020
Можете ли вы объяснить, почему n = n% len (seq)?
AerysS
16

Самый простой способ, которым я могу придумать:

a.append(a.pop(0))
Тайс
источник
3
Это самый быстрый способ для списков. collections.dequeбыстрее, но для большинства распространенных случаев длины списка в одной итерации или в любом случае нескольких итераций a.append(a.pop(0))будет быстрее, чем преобразование типов в deque
Purrell
@runDOSrun прекрасный ответ на этот вопрос, который, к сожалению, закрыт как дубликат. Может быть, вы проголосуете за его открытие?
волк
15

Если вы просто хотите перебирать эти наборы элементов, а не создавать отдельную структуру данных, рассмотрите возможность использования итераторов для создания выражения генератора:

def shift(l,n):
    return itertools.islice(itertools.cycle(l),n,n+len(l))

>>> list(shift([1,2,3],1))
[2, 3, 1]
Фил Х
источник
11

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

def shiftInPlace(l, n):
    n = n % len(l)
    head = l[:n]
    l[:n] = []
    l.extend(head)
    return l

На самом деле, даже добавление a l = l[:]к вершине этого для работы с копией переданного списка все равно в два раза быстрее.

Различные реализации с некоторым временем на http://gist.github.com/288272

keturn
источник
3
Вместо того, l[:n] = []чтобы пойти на del l[:n]. Просто альтернатива.
tzot
1
Ах да, старый добрый дель. Я часто забываю про дель; операция со списком - это оператор, а не метод. Py3k изменил эту причуду, или мы все еще получили это?
Кетурн
2
@keturn: delэто все еще заявление в Py3. Однако x.__delitem__(y) <==> del x[y], если вы предпочитаете использовать методы, l.__delitem__(slice(n))это также эквивалентно и работает в 2 и 3.
martineau
9

Несколько замечаний по срокам:

Если вы начинаете со списка, l.append(l.pop(0))это самый быстрый способ, который вы можете использовать. Это может быть показано только со сложностью времени:

  • deque.rotate - O (k) (k = количество элементов)
  • преобразование списка в деку - O (n)
  • list.append и list.pop оба O (1)

Так что, если вы начинаете с dequeобъектов, вы можете deque.rotate()за счет O (k). Но, если отправной точкой является список, временная сложность использования deque.rotate()составляет O (n). l.append(l.pop(0)быстрее в O (1).

Просто для иллюстрации, вот несколько примеров времени на 1M итераций:

Методы, которые требуют преобразования типов:

  • deque.rotateс объектом deque: 0.12380790710449219 секунд (самый быстрый)
  • deque.rotateс преобразованием типов: 6,853878974914551 секунд
  • np.rollс nparray: 6.0491721630096436 секунд
  • np.rollс преобразованием типов: 27,558452129364014 секунд

Перечислите методы, упомянутые здесь:

  • l.append(l.pop(0)): 0,32483696937561035 секунд (самый быстрый)
  • " shiftInPlace": 4,819645881652832 секунд
  • ...

Временной код используется ниже.


collections.deque

Показывает, что создание заявок из списков - это O (n):

from collections import deque
import big_o

def create_deque_from_list(l):
     return deque(l)

best, others = big_o.big_o(create_deque_from_list, lambda n: big_o.datagen.integers(n, -100, 100))
print best

# --> Linear: time = -2.6E-05 + 1.8E-08*n

Если вам нужно создать объекты deque:

1M итераций @ 6,853878974914551 секунд

setup_deque_rotate_with_create_deque = """
from collections import deque
import random
l = [random.random() for i in range(1000)]
"""

test_deque_rotate_with_create_deque = """
dl = deque(l)
dl.rotate(-1)
"""
timeit.timeit(test_deque_rotate_with_create_deque, setup_deque_rotate_with_create_deque)

Если у вас уже есть объекты deque:

1M итераций @ 0.12380790710449219 секунд

setup_deque_rotate_alone = """
from collections import deque
import random
l = [random.random() for i in range(1000)]
dl = deque(l)
"""

test_deque_rotate_alone= """
dl.rotate(-1)
"""
timeit.timeit(test_deque_rotate_alone, setup_deque_rotate_alone)

np.roll

Если вам нужно создать nparrays

1M итераций @ 27,558452129364014 секунд

setup_np_roll_with_create_npa = """
import numpy as np
import random
l = [random.random() for i in range(1000)]
"""

test_np_roll_with_create_npa = """
np.roll(l,-1) # implicit conversion of l to np.nparray
"""

Если у вас уже есть nparrays:

1M итераций @ 6.0491721630096436 секунд

setup_np_roll_alone = """
import numpy as np
import random
l = [random.random() for i in range(1000)]
npa = np.array(l)
"""

test_roll_alone = """
np.roll(npa,-1)
"""
timeit.timeit(test_roll_alone, setup_np_roll_alone)

«Сдвиг на место»

Не требует преобразования типа

1M итераций @ 4.819645881652832 секунд

setup_shift_in_place="""
import random
l = [random.random() for i in range(1000)]
def shiftInPlace(l, n):
    n = n % len(l)
    head = l[:n]
    l[:n] = []
    l.extend(head)
    return l
"""

test_shift_in_place="""
shiftInPlace(l,-1)
"""

timeit.timeit(test_shift_in_place, setup_shift_in_place)

l.append (l.pop (0))

Не требует преобразования типа

1M итераций @ 0.32483696937561035

setup_append_pop="""
import random
l = [random.random() for i in range(1000)]
"""

test_append_pop="""
l.append(l.pop(0))
"""
timeit.timeit(test_append_pop, setup_append_pop)
Purrell
источник
2
в то время как list.pop () является операцией с постоянным временем, list.pop (0) - нет . Он работает за линейное время относительно длины списка. Вы можете проверить , что путем изменения настройки timeit:l = [random.random() for i in range(100000)]
эму
1
list.pop не является операцией с постоянным временем. list.pop выполняется за время O (k), где k - количество элементов после удаленного элемента, поэтому list.pop (0) - O (n). Внутренне, list.pop использует list_ass_slice, который использует memmove для перемещения элементов быстрее, чем вы когда-либо могли с python, но для длинных списков это все еще очень много времени. См github.com/python/cpython/blob/master/Objects/listobject.c и wiki.python.org/moin/TimeComplexity
DRayX
Спасибо за выбор времени (и комментарии @emu). Итак, можем ли мы сказать, что l.append(l.pop(0))лучше всего сдвигать короткие списки (около 7 элементов) на один?
Вольф
Опять же, относительно l.append(l.pop(0))ответа: этот вопрос закрыт как дубликат. Может быть, вы проголосуете за его открытие?
Волк
8

Я также заинтересовался этим и сравнил некоторые из предложенных решений с perfplot ( мой маленький проект).

Оказывается, что

for _ in range(n):
    data.append(data.pop(0))

является на сегодняшний день самым быстрым способом для малых сдвигов n.

Для больших n,

data[n:] + data[:n]

не плохо

По сути, perfplot выполняет сдвиг для увеличения больших массивов и измеряет время. Вот результаты:

shift = 1:

введите описание изображения здесь

shift = 100:

введите описание изображения здесь


Код для воспроизведения сюжета:

import numpy
import perfplot
import collections


shift = 100


def list_append(data):
    return data[shift:] + data[:shift]


def shift_concatenate(data):
    return numpy.concatenate([data[shift:], data[:shift]])


def roll(data):
    return numpy.roll(data, -shift)


def collections_deque(data):
    items = collections.deque(data)
    items.rotate(-shift)
    return items


def pop_append(data):
    for _ in range(shift):
        data.append(data.pop(0))
    return data


perfplot.save(
    "shift100.png",
    setup=lambda n: numpy.random.rand(n).tolist(),
    kernels=[list_append, roll, shift_concatenate, collections_deque, pop_append],
    n_range=[2 ** k for k in range(7, 20)],
    logx=True,
    logy=True,
    xlabel="len(data)",
)
Нико Шлёмер
источник
Хороший инструмент, который вы создали. По поводу l.append(l.pop(0))ответа: Этот вопрос закрыт как дубликат. Может быть, вы проголосуете за его открытие?
волк
4

Возможно, кольцевой буфер больше подходит. Это не список, хотя вполне вероятно, что он может вести себя достаточно как список для ваших целей.

Проблема в том, что эффективность изменения списка составляет O (n), что становится значительным для достаточно больших списков.

Сдвиг в кольцевом буфере - это просто обновление местоположения головы, которое равно O (1)

Джон Ла Рой
источник
4

Для неизменной реализации вы можете использовать что-то вроде этого:

def shift(seq, n):
    shifted_seq = []
    for i in range(len(seq)):
        shifted_seq.append(seq[(i-n) % len(seq)])
    return shifted_seq

print shift([1, 2, 3, 4], 1)
Bittercoder
источник
3

Если ваша цель - эффективность (циклы? Память?), Вам может быть лучше взглянуть на модуль массива: http://docs.python.org/library/array.html

Массивы не имеют накладных расходов списков.

Что касается чистых списков, то, что у вас есть, настолько хорошо, насколько вы можете надеяться сделать.

рекурсивный
источник
3

Я думаю, что вы ищете это:

a.insert(0, x)
redreamality
источник
Я не вижу связи между вопросом и вашим ответом. Можете ли вы объяснить это?
Вольф
2

Другая альтернатива:

def move(arr, n):
    return [arr[(idx-n) % len(arr)] for idx,_ in enumerate(arr)]
damio
источник
1

Я принимаю эту модель стоимости в качестве ссылки:

http://scripts.mit.edu/~6.006/fall07/wiki/index.php?title=Python_Cost_Model

Ваш метод нарезки списка и объединения двух подсписков - это операции с линейным временем. Я бы предложил использовать pop, который является операцией постоянного времени, например:

def shift(list, n):
    for i in range(n)
        temp = list.pop()
        list.insert(0, temp)
herrfz
источник
2
Обновление: возьмите это как лучший справочник: wiki.python.org/moin/TimeComplexity , используйте collections.dequeuepop и appendleft, которые оба являются O (1) ops. В моем первом ответе выше, вставить это O (n).
herrfz
1
должно бытьcollections.deque
herrfz
1

Я не знаю, является ли это «эффективным», но это также работает:

x = [1,2,3,4]
x.insert(0,x.pop())

РЕДАКТИРОВАТЬ: Привет еще раз, я только что нашел большую проблему с этим решением! Рассмотрим следующий код:

class MyClass():
    def __init__(self):
        self.classlist = []

    def shift_classlist(self): # right-shift-operation
        self.classlist.insert(0, self.classlist.pop())

if __name__ == '__main__':
    otherlist = [1,2,3]
    x = MyClass()

    # this is where kind of a magic link is created...
    x.classlist = otherlist

    for ii in xrange(2): # just to do it 2 times
        print '\n\n\nbefore shift:'
        print '     x.classlist =', x.classlist
        print '     otherlist =', otherlist
        x.shift_classlist() 
        print 'after shift:'
        print '     x.classlist =', x.classlist
        print '     otherlist =', otherlist, '<-- SHOULD NOT HAVE BIN CHANGED!'

Метод shift_classlist () выполняет тот же код, что и мой x.insert (0, x.pop ()) - решение, otherlist - это список, независимый от класса. После передачи содержимого otherlist в список MyClass.classlist вызов функции shift_classlist () также изменяет список других списков:

КОНСОЛЬНЫЙ ВЫХОД:

before shift:
     x.classlist = [1, 2, 3]
     otherlist = [1, 2, 3]
after shift:
     x.classlist = [3, 1, 2]
     otherlist = [3, 1, 2] <-- SHOULD NOT HAVE BIN CHANGED!



before shift:
     x.classlist = [3, 1, 2]
     otherlist = [3, 1, 2]
after shift:
     x.classlist = [2, 3, 1]
     otherlist = [2, 3, 1] <-- SHOULD NOT HAVE BIN CHANGED!

Я использую Python 2.7. Я не знаю, является ли это ошибкой, но я думаю, что более вероятно, что я что-то не так понял здесь.

Кто-нибудь из вас знает, почему это происходит?

wese3112
источник
2
Это происходит потому, что x.classlist = otherlistзаставляет x.classlistобращаться к тому же списку, что otherlistи тогда, когда вы вызываете x.shift_classlist()его, изменяет список и потому что оба имени ссылаются на один и тот же объект списка. Кажется, что оба имени меняются, потому что это просто псевдонимы для одного и того же объекта Используйте x.classlist = otherlist[:]вместо этого, чтобы назначить копию списка.
Дэн Д.
Эй, вау! Большое спасибо! Я действительно не знал этого, и это действительно приятно знать! :)
wese3112
1

Следующий метод - это O (n) с постоянной вспомогательной памятью:

def rotate(arr, shift):
  pivot = shift % len(arr)
  dst = 0
  src = pivot
  while (dst != src):
    arr[dst], arr[src] = arr[src], arr[dst]
    dst += 1
    src += 1
    if src == len(arr):
      src = pivot
    elif dst == pivot:
      pivot = src

Обратите внимание, что в python этот подход ужасно неэффективен по сравнению с другими, поскольку он не может использовать преимущества собственных реализаций какой-либо части.

DRayX
источник
ну, на самом деле вы могли бы использовать list.pop и list.append. Язык не виноват, что вы написали 12-строчную функцию, которая является O (n), когда вы могли просто написать «l.append (l.pop (0))», которая является постоянным временем.
Purrell
l.append (l.pop (0)) - это O (n) (l.pop (0) должен сдвигать каждый элемент), таким образом, если вы хотите сдвинуть m значений, сложность на самом деле O (n * m). Сложность алгоритма, который я предоставил, составляет O (n) независимо от количества смен. На практике это происходит медленно, потому что так много логики выполняется в операциях Python вместо C (list.pop реализован в c, см. Github.com/python/cpython/blob/master/Objects/listobject.c ).
DRayX
1

У меня есть похожая вещь. Например, сдвинуться на два ...

def Shift(*args):
    return args[len(args)-2:]+args[:len(args)-2]
EyoelD
источник
1

Я думаю, у вас есть самый эффективный способ

def shift(l,n):
    n = n % len(l)  
    return l[-U:] + l[:-U]
Джон Ктехик
источник
0

Какой вариант использования? Часто нам фактически не нужен полностью сдвинутый массив - нам просто нужно получить доступ к нескольким элементам в сдвинутом массиве.

Получение срезов Python - это время выполнения O (k), где k - это срез, поэтому ротация срезов - это время выполнения N. Команда вращения deque также O (k). Можем ли мы сделать лучше?

Рассмотрим массив, который очень большой (скажем, настолько большой, что его нарезка будет вычислительно медленной). Альтернативным решением было бы оставить исходный массив в покое и просто вычислить индекс элемента, который существовал бы в нашем желаемом индексе после какого-либо сдвига.

Таким образом, доступ к смещенному элементу становится O (1).

def get_shifted_element(original_list, shift_to_left, index_in_shifted):
    # back calculate the original index by reversing the left shift
    idx_original = (index_in_shifted + shift_to_left) % len(original_list)
    return original_list[idx_original]

my_list = [1, 2, 3, 4, 5]

print get_shifted_element(my_list, 1, 2) ----> outputs 4

print get_shifted_element(my_list, -2, 3) -----> outputs 2 
Ник Ли
источник
0

Следующая функция копирует отправленный список во временный список, чтобы функция pop не влияла на исходный список:

def shift(lst, n, toreverse=False):
    templist = []
    for i in lst: templist.append(i)
    if toreverse:
        for i in range(n):  templist = [templist.pop()]+templist
    else:
        for i in range(n):  templist = templist+[templist.pop(0)]
    return templist

Тестирование:

lst = [1,2,3,4,5]
print("lst=", lst)
print("shift by 1:", shift(lst,1))
print("lst=", lst)
print("shift by 7:", shift(lst,7))
print("lst=", lst)
print("shift by 1 reverse:", shift(lst,1, True))
print("lst=", lst)
print("shift by 7 reverse:", shift(lst,7, True))
print("lst=", lst)

Вывод:

lst= [1, 2, 3, 4, 5]
shift by 1: [2, 3, 4, 5, 1]
lst= [1, 2, 3, 4, 5]
shift by 7: [3, 4, 5, 1, 2]
lst= [1, 2, 3, 4, 5]
shift by 1 reverse: [5, 1, 2, 3, 4]
lst= [1, 2, 3, 4, 5]
shift by 7 reverse: [4, 5, 1, 2, 3]
lst= [1, 2, 3, 4, 5]
rnso
источник
0

Джон Бентли из « Программирование жемчужин» (столбец 2) описывает элегантный и эффективный алгоритм поворота nвектора -элемента, xоставленного iпозициями:

Давайте рассмотрим проблему как преобразование массива abв массив ba, но давайте также предположим, что у нас есть функция, которая инвертирует элементы в указанной части массива. Начнем с того ab, что мы обращаемся aк получению , возвращаемся к получению , а затем полностью обращаемся к получению , что точно . Это приводит к следующему коду для ротации:arbbarbr(arbr)rba

reverse(0, i-1)
reverse(i, n-1)
reverse(0, n-1)

Это может быть переведено на Python следующим образом:

def rotate(x, i):
    i %= len(x)
    x[:i] = reversed(x[:i])
    x[i:] = reversed(x[i:])
    x[:] = reversed(x)
    return x

Демо-версия:

>>> def rotate(x, i):
...     i %= len(x)
...     x[:i] = reversed(x[:i])
...     x[i:] = reversed(x[i:])
...     x[:] = reversed(x)
...     return x
... 
>>> rotate(list('abcdefgh'), 1)
['b', 'c', 'd', 'e', 'f', 'g', 'h', 'a']
>>> rotate(list('abcdefgh'), 3)
['d', 'e', 'f', 'g', 'h', 'a', 'b', 'c']
>>> rotate(list('abcdefgh'), 8)
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
>>> rotate(list('abcdefgh'), 9)
['b', 'c', 'd', 'e', 'f', 'g', 'h', 'a']
Евгений Ярмаш
источник
0

Для списка X = ['a', 'b', 'c', 'd', 'e', 'f']и желаемого значения сдвига, shift меньшего длины списка , мы можем определить функцию, list_shift()как показано ниже

def list_shift(my_list, shift):
    assert shift < len(my_list)
    return my_list[shift:] + my_list[:shift]

Примеры,

list_shift(X,1)возвращается ['b', 'c', 'd', 'e', 'f', 'a'] list_shift(X,3)возвращается['d', 'e', 'f', 'a', 'b', 'c']

helcode
источник
1
Это именно то, что есть у ОП. Вы просто изменили имена и добавили подтверждение.
RufusVS
Функция list_shiftв вашем ответе идентична функции shiftв исходном вопросе, так что это не ответ на реальный вопрос: «Есть ли лучший способ?»
RufusVS
0
def solution(A, K):
    if len(A) == 0:
        return A

    K = K % len(A)

    return A[-K:] + A[:-K]

# use case
A = [1, 2, 3, 4, 5, 6]
K = 3
print(solution(A, K))

Например, учитывая

A = [3, 8, 9, 7, 6]
K = 3

функция должна вернуться [9, 7, 6, 3, 8]. Три поворота были сделаны:

[3, 8, 9, 7, 6] -> [6, 3, 8, 9, 7]
[6, 3, 8, 9, 7] -> [7, 6, 3, 8, 9]
[7, 6, 3, 8, 9] -> [9, 7, 6, 3, 8]

Для другого примера, приведенного

A = [0, 0, 0]
K = 1

функция должна вернуться [0, 0, 0]

Дано

A = [1, 2, 3, 4]
K = 4

функция должна вернуться [1, 2, 3, 4]

Ракеш Кумар
источник
0

Я искал на месте решение этой проблемы. Это решает цель в O (k).

def solution(self, list, k):
    r=len(list)-1
    i = 0
    while i<k:
        temp = list[0]
        list[0:r] = list[1:r+1]
        list[r] = temp
        i+=1
    return list
Анкит
источник
-3

для аналогичной функциональности, как сдвиг в других языках:

def shift(l):
    x = l[0]
    del(l[0])
    return x
Дэвид
источник
1
-1: это делает что-то отличное от того, о чем спрашивают, и BTW также эквивалентноL.pop(0)
6502