Maneira eficiente de girar uma lista em python

263

Qual é a maneira mais eficiente de rotacionar uma lista em python? Agora eu tenho algo parecido com isto:

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

Existe uma maneira melhor?

dzhelil
fonte
12
Isso não é realmente uma mudança, pois os outros idiomas (Perl, Ruby) usam o termo. Isso é rodar. Talvez a pergunta deva ser atualizada de acordo?
Vincent Fourmond
@dzhelil Eu realmente gosto de sua solução original, porque ela não introduz mutações
Juanchito
2
numpy.roll
BoltzmannBrain
2
Eu acho que rotateé a palavra certa, não shift.
codeforester
2
A verdadeira resposta correta, é que você nunca deve ser rotativa da lista em primeiro lugar. Crie uma variável "ponteiro" para o local lógico da sua lista onde deseja que a "cabeça" ou a "cauda" estejam e altere essa variável em vez de mover qualquer um dos itens da lista. Procure o operador "módulo"% para a maneira eficiente de "agrupar" o ponteiro no início e no final da lista.
cnd

Respostas:

280

UMA collections.deque é otimizado para puxar e empurrar nas duas extremidades. Eles ainda têm um rotate()método dedicado .

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]
Ignacio Vazquez-Abrams
fonte
8
Para futuros leitores: collections.deque rotate()é mais rápido do que fatiar de acordo com wiki.python.org/moin/TimeComplexity
Geoff
2
Mas esteja ciente, o uso deque.rotaterequer uma conversão de tipo para um dequeobjeto primeiro, que é mais lento que l.append(l.pop(0)). Portanto, se você tem um objeto deque para começar, verifique se ele é o mais rápido. Caso contrário, use l.append(l.pop(0)).
Purrell
8
Para elaborar, deque.rotateé O (k), mas a conversão de tipo da lista para deque é O (n) . Portanto, se você começar com uma lista, usar deque.rotate é O (n) + O (k) = O (n). l.append(l.pop(0))por outro lado, é O (1).
Purrell
3
@Purrell, estalar o item da frente é O (n). No wiki.python.org/moin/TimeComplexity, ele é listado como O (k), ek é o número de elementos na lista após o item exibido, porque a estrutura de dados muda todos os seguintes elementos para a frente da lista. Somente o último elemento pode ser exibido no tempo O (1) por esse motivo.
Kirk Boyer
88

Que tal apenas usar pop(0)?

list.pop([i])

Remova o item na posição especificada na lista e devolva-o. Se nenhum índice for especificado, a.pop()remove e retorna o último item da lista. (Os colchetes ao redor da iassinatura do método indicam que o parâmetro é opcional, não que você deva digitar colchetes nessa posição. Você verá essa notação frequentemente na Referência da Biblioteca Python.)

Jamgold
fonte
16
Mas não custaria O (k) para remover cada elemento da lista em que k é o número de elementos restantes. Portanto, o tempo total será O (n ^ 2) wiki.python.org/moin/TimeComplexity
Pramod
5
Isso realmente não responde à pergunta. A questão não é retornar itens em ordem, mas criar uma nova lista que esteja em uma ordem diferente.
user650261
5
não, a resposta para a pergunta usando pop seria l.append(l.pop(0). O que, se não me engano, é O (1).
Purrell
4
list.pop chama internamente list_ass_slice, que usa o memmove para mover muito rapidamente todos os itens, mas ainda é O (n). Consulte github.com/python/cpython/blob/master/Objects/listobject.c e wiki.python.org/moin/TimeComplexity . O único item que pode ser removido de uma lista python em tempo constante é o último.
DRayX 28/07/19
2
Votado. Em docs.python.org/3/tutorial/… Também é possível usar uma lista como uma fila, onde o primeiro elemento adicionado é o primeiro elemento recuperado (“primeiro a entrar , primeiro a sair”); no entanto, as listas não são eficientes para esse fim. Embora os anexos e pops do final da lista sejam rápidos, fazer inserções ou pops no início de uma lista é lento (porque todos os outros elementos precisam ser alterados por um).
SantaXL 5/05/19
59

O Numpy pode fazer isso usando o rollcomando:

>>> 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])
Richard
fonte
1
O que eu amo sobre isso é que às vezes as respostas de alimentação você pode encontrar alguns grandes novos tesouros como este :)
noamgot
Isso, quando eu testei, é muito, muito lento
Peter Harrison
@ PeterHarrison: Como você não fornece detalhes dos testes, é difícil saber o que você quer dizer. Esta resposta fornece detalhes completos dos testes e uma comparação de tempo.
Richard
33

Depende do que você deseja que aconteça ao fazer isso:

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

Você pode alterar seu:

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

para:

def shift(seq, n):
    n = n % len(seq)
    return seq[n:] + seq[:n]
jcdyer
fonte
5
NB: Isso trava para listas vazias.
meawoppl
n = n% len (seq) return = seq [-n:] + seq [: - n]
user3303020
Você pode explicar por que n = n% len (seq)?
AerysS
16

A maneira mais simples de pensar:

a.append(a.pop(0))
Thijs
fonte
3
Este é o caminho mais rápido para listas. collections.dequeé mais rápido, mas para a maioria dos casos comuns de comprimento lista em uma única iteração, ou qualquer caso de várias iterações, a.append(a.pop(0))vai ser mais rápido do que a conversão de tipo de deque
Purrell
@runDOSrun a resposta perfeita para esta pergunta que infelizmente está fechada como duplicata. Talvez você vote para reabri-lo?
Wolf
15

Se você deseja iterar sobre esses conjuntos de elementos em vez de construir uma estrutura de dados separada, considere usar iteradores para construir uma expressão de gerador:

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

>>> list(shift([1,2,3],1))
[2, 3, 1]
Phil H
fonte
11

Isso também depende se você deseja alterar a lista no lugar (modificá-la) ou se deseja que a função retorne uma nova lista. Porque, de acordo com meus testes, algo assim é pelo menos vinte vezes mais rápido que a sua implementação, que adiciona duas listas:

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

De fato, mesmo adicionando um l = l[:] ao topo para operar em uma cópia da lista passada ainda é duas vezes mais rápido.

Várias implementações com algum tempo em http://gist.github.com/288272

keturn
fonte
3
Em vez de l[:n] = []eu ir para del l[:n]. Apenas uma alternativa.
tzot
1
Ah, sim, bom e velho del. Costumo esquecer o del; a operação de lista que é uma declaração, não um método. O py3k mudou essa peculiaridade ou ainda a entendemos?
keturn
2
@keturn: delainda é uma declaração no Py3. No entanto x.__delitem__(y) <==> del x[y], por isso, se você preferir usar métodos, l.__delitem__(slice(n))também é equivalente e trabalha em ambos 2 e 3.
martineau
9

Apenas algumas notas sobre o tempo:

Se você está começando com uma lista, l.append(l.pop(0))é o método mais rápido que pode usar. Isso pode ser mostrado apenas com a complexidade do tempo:

  • deque.rotate é O (k) (k = número de elementos)
  • a conversão da lista em deque é O (n)
  • list.append e list.pop são ambos O (1)

Portanto, se você está começando com dequeobjetos, pode fazê-lo deque.rotate()ao custo de O (k). Mas, se o ponto de partida for uma lista, a complexidade do tempo de uso deque.rotate()será O (n). l.append(l.pop(0)é mais rápido em O (1).

Apenas para fins ilustrativos, aqui estão alguns exemplos de tempos nas iterações 1M:

Métodos que requerem conversão de tipo:

  • deque.rotatecom objeto deque: 0.12380790710449219 segundos (mais rápido)
  • deque.rotatecom conversão de tipo: 6.853878974914551 segundos
  • np.rollcom nparray: 6.0491721630096436 segundos
  • np.rollcom conversão de tipo: 27.558452129364014 segundos

Liste os métodos mencionados aqui:

  • l.append(l.pop(0)): 0.32483696937561035 segundos (mais rápido)
  • " shiftInPlace": 4.819645881652832 segundos
  • ...

O código de tempo usado está abaixo.


collections.deque

Mostrando que criar deques a partir de listas é 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

Se você precisar criar objetos deque:

1M iterações @ 6.853878974914551 segundos

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)

Se você já possui objetos deque:

1M iterações @ 0.12380790710449219 segundos

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

Se você precisar criar nparrays

1M iterações @ 27.558452129364014 segundos

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
"""

Se você já possui nparrays:

1M iterações @ 6.0491721630096436 segundos

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)

"Mudança no lugar"

Não requer conversão de tipo

1M iterações @ 4.819645881652832 segundos

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))

Não requer conversão de tipo

1M iterações @ 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
fonte
2
enquanto list.pop () é uma operação de tempo constante, list.pop (0) não é . É executado em tempo linear com relação ao comprimento da lista. Você pode testar isso modificando sua configuração de timeit:l = [random.random() for i in range(100000)]
emu
1
list.pop não é uma operação de tempo constante. list.pop é executado no tempo O (k) em que k é o número de elementos após o elemento removido, portanto list.pop (0) é O (n). Internamente, o list.pop usa list_ass_slice, que usa o memmove para mover itens muito mais rápido do que você jamais poderia com o python, mas, para listas longas, ainda consome muito tempo. Veja github.com/python/cpython/blob/master/Objects/listobject.c e wiki.python.org/moin/TimeComplexity
DRayX:
Obrigado pelo tempo (e comentários @emu). Então, podemos dizer que l.append(l.pop(0))é o melhor desempenho para mudar listas curtas (cerca de 7 elementos) por um?
Wolf
Novamente, concernente l.append(l.pop(0))como resposta: Esta pergunta está encerrada como duplicada. Talvez você vote para reabri-lo?
Wolf
8

Também me interessei por isso e comparei algumas das soluções sugeridas com o perfplot (um pequeno projeto meu).

Acontece que

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

é de longe o método mais rápido para pequenos turnos n.

Para maiores n,

data[n:] + data[:n]

não é ruim.

Essencialmente, o perfplot executa o turno para aumentar matrizes grandes e mede o tempo. Aqui estão os resultados:

shift = 1:

insira a descrição da imagem aqui

shift = 100:

insira a descrição da imagem aqui


Código para reproduzir o gráfico:

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)",
)
Nico Schlömer
fonte
Boa ferramenta que você construiu. Concernente l.append(l.pop(0))como resposta: Esta pergunta está encerrada como duplicada. Talvez você vote para reabri-lo?
Wolf
4

Possivelmente um ringbuffer é mais adequado. Não é uma lista, embora seja provável que ela possa se comportar o suficiente como uma lista para seus propósitos.

O problema é que a eficiência de uma mudança em uma lista é O (n), que se torna significativa para listas grandes o suficiente.

Mudar em um ringbuffer é simplesmente atualizar o local da cabeça que é O (1)

John La Rooy
fonte
4

Para uma implementação imutável, você pode usar algo como isto:

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
fonte
3

Se a sua meta é a eficiência (ciclos? Memória?), É melhor observar o módulo do array: http://docs.python.org/library/array.html

Matrizes não têm a sobrecarga de listas.

No entanto, no que diz respeito às listas puras, o que você tem é tão bom quanto você espera fazer.

recursivo
fonte
3

Eu acho que você está procurando por isso:

a.insert(0, x)
redreamalidade
fonte
Não vejo a relação entre a pergunta e sua resposta. Você pode por favor explicar?
Wolf
2

Outra alternativa:

def move(arr, n):
    return [arr[(idx-n) % len(arr)] for idx,_ in enumerate(arr)]
Damio
fonte
1

Tomo esse modelo de custo como referência:

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

Seu método de fatiar a lista e concatenar duas sub-listas são operações de tempo linear. Eu sugeriria o uso de pop, que é uma operação de tempo constante, por exemplo:

def shift(list, n):
    for i in range(n)
        temp = list.pop()
        list.insert(0, temp)
herrfz
fonte
2
update: use isso como uma referência melhor: wiki.python.org/moin/TimeComplexity , use collections.dequeuepop e appendleft, que são O (1) ops. Na minha primeira resposta acima, insert é O (n).
21412 herrfz
1
deveria sercollections.deque
herrfz
1

Não sei se isso é 'eficiente', mas também funciona:

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

EDIT: Olá novamente, acabei de encontrar um grande problema com esta solução! Considere o seguinte código:

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!'

O método shift_classlist () executa o mesmo código que minha solução x.insert (0, x.pop ()) -, otherlist é uma lista independente da classe. Depois de passar o conteúdo de otherlist para a lista MyClass.classlist, chamar shift_classlist () também altera a lista de otherlist:

SAÍDA DA CONSOLA:

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!

Eu uso o Python 2.7. Não sei se isso é um bug, mas acho que é mais provável que eu tenha entendido algo errado aqui.

Alguém sabe por que isso acontece?

wese3112
fonte
2
Isso acontece porque x.classlist = otherlistmarcas se x.classlistreferem à mesma lista otherliste quando você a chama x.shift_classlist()muda a lista e porque os dois nomes se referem ao mesmo objeto de lista. Ambos os nomes parecem mudar porque são apenas aliases para o mesmo objeto. Use x.classlist = otherlist[:]para atribuir uma cópia da lista.
Dan D.
Ei, uau! Muito obrigado! Eu realmente não sabia disso e é muito bom saber! :)
wese3112
1

O método a seguir está O (n) em vigor com memória auxiliar constante:

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

Observe que, em python, essa abordagem é terrivelmente ineficiente em comparação com outras, pois não pode tirar proveito das implementações nativas de nenhuma das partes.

DRayX
fonte
bem, na verdade você pode usar list.pop e list.append. Não é culpa do idioma que você escreveu uma função de 12 linhas que é O (n), quando você poderia ter escrito "l.append (l.pop (0))", que é tempo constante.
Purrell
l.append (l.pop (0)) é O (n) (l.pop (0) precisa mudar todos os elementos), portanto, se você deseja alterar os valores de m, a complexidade é realmente O (n * m). A complexidade do algoritmo que forneci é O (n), independentemente do número de turnos. Na prática, isso é lento porque muita lógica é feita nas operações de python em vez de C (a lista.pop é implementada em c, consulte github.com/python/cpython/blob/master/Objects/listobject.c ).
DRayX 28/07/19
1

Eu tenho coisa parecida. Por exemplo, para mudar por dois ...

def Shift(*args):
    return args[len(args)-2:]+args[:len(args)-2]
EyoelD
fonte
1

Eu acho que você tem a maneira mais eficiente

def shift(l,n):
    n = n % len(l)  
    return l[-U:] + l[:-U]
john ktejik
fonte
0

Qual é o caso de uso? Frequentemente, na verdade não precisamos de uma matriz totalmente deslocada - precisamos apenas acessar alguns elementos na matriz deslocada.

Obter fatias do Python é o tempo de execução O (k), onde k é a fatia, portanto, uma rotação fatiada é o tempo de execução N. O comando deque rotation também é O (k). Podemos fazer melhor?

Considere uma matriz extremamente grande (digamos, tão grande que seria computacionalmente lenta para cortá-la). Uma solução alternativa seria deixar a matriz original em paz e simplesmente calcular o índice do item que existiria no índice desejado após uma mudança de algum tipo.

O acesso a um elemento deslocado passa a ser 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 
Nick Lee
fonte
0

A função a seguir copia a lista enviada para um modelo, para que a função pop não afete a lista original:

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

Teste:

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)

Resultado:

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
fonte
0

Jon Bentley em Programming Pearls (Coluna 2) descreve um algoritmo elegante e eficiente para rotacionar um nvetor de elemento xdeixado pelas iposições:

Vamos ver o problema como transformar a matriz abem uma matriz ba, mas também vamos assumir que temos uma função que reverte os elementos em uma parte especificada da matriz. Começando com ab, invertemos apara obter , invertemos para obter e depois invertemos a coisa toda para obter , o que é exatamente . Isso resulta no seguinte código para rotação:arbbarbr(arbr)rba

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

Isso pode ser traduzido para Python da seguinte maneira:

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

Demo:

>>> 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']
Eugene Yarmash
fonte
0

Para uma lista X = ['a', 'b', 'c', 'd', 'e', 'f']e um valor de turno desejado shift menor que o tamanho da lista , podemos definir a função list_shift()como abaixo

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

Exemplos,

list_shift(X,1)retorna ['b', 'c', 'd', 'e', 'f', 'a'] list_shift(X,3)retorna['d', 'e', 'f', 'a', 'b', 'c']

helcode
fonte
1
É exatamente isso que o OP tem. Você acabou de alterar os nomes e adicionou uma declaração.
RufusVS 22/1018
A função list_shiftna sua resposta é idêntica à da shiftpergunta original, portanto, essa não é uma resposta à pergunta real: "Existe uma maneira melhor?"
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))

Por exemplo, dado

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

a função deve retornar [9, 7, 6, 3, 8]. Foram realizadas três rotações:

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

Por outro exemplo, dado

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

a função deve retornar [0, 0, 0]

Dado

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

a função deve retornar [1, 2, 3, 4]

Rakesh Kumar
fonte
0

Eu estava procurando uma solução para esse problema. Isso resolve o objetivo em 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
Ankit
fonte
-3

para funcionalidade semelhante à mudança em outros idiomas:

def shift(l):
    x = l[0]
    del(l[0])
    return x
David
fonte
1
-1: Isso está fazendo algo diferente do que é solicitado, e BTW também é equivalente aL.pop(0)
6502 8/08