Valores cíclicos de una lista


Soy nuevo en la codificación y estoy tratando de escribir un código simple que tomará una lista, por ejemplo [1,2,3] y ciclo de los elementos n número de veces. Así que si n=1, debería obtener A = [3,1,2]. Si n = 2, debería obtener A = [2,3,1].El código que he escrito es:

n=1
j=0
A = [1,2,3]
B = [None]*len(A)

while j<=n:
     for i in range(0,len(A)):
         B[i] = A[-1+i]
     j=j+1
print(B)

El problema es que no importa cuál sea el valor de n, obtengo la misma respuesta que solo es un ciclo una vez. Creo que el problema es que el bucle está circulando a través de la misma B cada vez, así que necesito almacenar la nueva B como algo más y luego repetir el bucle con la nueva B. Pero no puedo averiguar cómo hacer eso. Cualquier consejo sería apreciado

Author: martineau, 2018-10-06

6 answers

Creo que lo estás complicando demasiado. Considere cambiarlo a algo como lo siguiente:

n = 1
A = [1,2,3]
B = A.copy()

for _ in range(n):
    # Cycle through by concatenating the last element and all other elements together 
    B = [B[-1]]+B[0:-1]

print(B)

En el caso de n=1, obtienes [3, 1, 2], y n=2 te da [2, 3, 1]

Tenga en cuenta que lo que está tratando de hacer se implementa en numpy.roll (Supongo que está preguntando sobre el proceso, no el resultado, sino por si acaso)

import numpy as np

>>> np.roll(A,1)
array([3, 1, 2])
>>> np.roll(A,2)
array([2, 3, 1])
 6
Author: sacul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-10-06 00:11:05

Una función más simple para esto es:

def roll(L, n):
    n %= len(L)
    return L[-n:] + L[:-n]

A = [1,2,3]
roll(A, 1)   # [3, 1, 2]
roll(A, 2)   # [2, 3, 1]
roll(A, 3)   # [1, 2, 3]
roll(A, 4)   # [3, 1, 2]

Tomar el módulo (n %= len(L)) evita la necesidad de seguir circulando. A continuación, solo concatenar una rebanada de tamaño apropiado del final de la lista al principio de la misma.

 4
Author: Stuart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-10-06 01:32:39

Vea la respuesta de@sacul para el problema con su código. Pero list no es la estructura más apropiada para tal requisito ya que cada cambio tiene O(n) complejidad.

deque ("cola de doble extremo") del módulo collections proporciona esta característica a través de su método rotate. Este método funciona in-place y tiene complejidad O( k), donde k es un argumento que representa el número de rotaciones. He aquí un ejemplo:

from collections import deque

d = deque([1,2,3])
d.rotate(2)

print(d)

deque([2, 3, 1])
 2
Author: jpp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-10-06 10:43:00

La respuesta de @ sacul funciona, ¡pero estabas cerca! Te perdiste la actualización A para la siguiente iteración del bucle while después de crear tu nuevo B.

n=1
j=0
A = [1,2,3]
B = [None]*len(A)

while j<=n:
    for i in range(0,len(A)):
        B[i] = A[-1+i]
    A = B[:] # update A so that next time B works on the new A 
    print('A is now ', A) # to debug
    j=j+1

print(B)

Esto resulta en las siguientes declaraciones de impresión:

A is now  [3, 1, 2]                                                                                                                   
A is now  [2, 3, 1]                                                                                                                   
[2, 3, 1] # this is what finally B is
 0
Author: slider,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-10-06 01:16:17

Una solución basada en itertools

from itertools import cycle, islice

def roll(x, n):
    start = len(x) - n
    return islice(cycle(x), start, start + len(x))

Si hacemos un ciclo a través de los valores en x (en realidad solo lo haríamos a lo sumo dos veces). Luego córtalo para que comience en el elemento que queremos e incluya el número correcto de elementos.

Es probablemente un poco más esotérico que algunas de las otras soluciones, pero vale la pena tirar en la bolsa, dado que hay tantas alternativas.

itertools.islice devuelve un generador. Si desea imprimir el resultado, debe convertirlo a list.

 0
Author: Paul Rooney,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-10-06 02:05:52

No voy a profundizar ya que alguien ya respondió a tu pregunta.. Pero una propiedad importante a tener en cuenta aquí es también que

A = [1, 2, 3] #Assuming that the length of the matrix you want to rotate is of length 3

If you want to cycle/rotate by 3, then you want to actually cycle/rotate by `len(A)%3` = 0
If you want to cycle/rotate by 6, then you want to actually cycle/rotate by `len(A)%6` = 0
If you want to cycle/rotate by 4, then you want to actually cycle/rotate by `len(A)%3` = 1
If you want to cycle/rotate by a number lesser than the length itself.. then just rotate it by that number!

so if you want to cycle by 2, then well.. rotate it by two.. 
 -1
Author: Abhishek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-10-06 00:53:31