¿Cómo cambiar la posición de dos elementos en una lista de Python?

208

No he podido encontrar una buena solución para este problema en la red (probablemente porque interruptor, posición, lista y Python son palabras tan sobrecargadas).

Es bastante simple: tengo esta lista:

['title', 'email', 'password2', 'password1', 'first_name', 'last_name', 'next', 'newsletter']

Me gustaría cambiar la posición de 'password2'y 'password1', sin saber su posición exacta, solo que están uno al lado del otro y password2son los primeros.

He logrado esto con algunos suscriptores de lista bastante largos, pero me preguntaba si es posible llegar a algo un poco más elegante.

mikl
fuente
¿Es su problema la eficiencia de tratar de encontrar 'contraseña2' en la lista? ¿Puede 'contraseña1' ir antes que 'contraseña2'? ¿Hay alguna complejidad aquí que no se encuentre en su pregunta original? De lo contrario, estoy de acuerdo con @unwind.
Brent escribe el código el
3
Debería publicar lo que tiene: tengo curiosidad sobre lo que quiere decir con una "suscripción de lista bastante larga".
samtregar
Algo similar a index1 = index ('contraseña1'); index2 = index ('contraseña2'); order = order [: index2] .append (order [index1]). append (order [index2]). append (order [index1 + 1:]); se extendió en unas pocas líneas más. Bonita no
mikl 22/03/10

Respuestas:

393
    i = ['title', 'email', 'password2', 'password1', 'first_name', 
         'last_name', 'next', 'newsletter']
    a, b = i.index('password2'), i.index('password1')
    i[b], i[a] = i[a], i[b]
samtregar
fuente
165

El simple intercambio de Python se ve así:

foo[i], foo[j] = foo[j], foo[i]

Ahora todo lo que necesita hacer es calcular qué ies, y eso se puede hacer fácilmente con index:

i = foo.index("password2")
Can Berk Güder
fuente
15

Dadas sus especificaciones, usaría la asignación de corte:

>>> L = ['title', 'email', 'password2', 'password1', 'first_name', 'last_name', 'next', 'newsletter']
>>> i = L.index('password2')
>>> L[i:i+2] = L[i+1:i-1:-1]
>>> L
['title', 'email', 'password1', 'password2', 'first_name', 'last_name', 'next', 'newsletter']

El lado derecho de la asignación de corte es un "corte invertido" y también podría escribirse:

L[i:i+2] = reversed(L[i:i+2])

si lo encuentra más legible, como muchos lo harían.

Alex Martelli
fuente
¿Por qué esto no funciona si desea cambiar el título y el correo, el primer elemento con el segundo?
Luigi Tiburzi
Lo siento, ahora entiendo, no hay elementos en i-1, por lo que se devuelve una lista vacía
Luigi Tiburzi
7

¿Cómo puede ser más largo que

tmp = my_list[indexOfPwd2]
my_list[indexOfPwd2] = my_list[indexOfPwd2 + 1]
my_list[indexOfPwd2 + 1] = tmp

Eso es solo un intercambio simple usando almacenamiento temporal.

relajarse
fuente
13
Si quieres ser realmente "Pythonic" al respecto, siempre puedes hacer esto también:my_list[indexOfPwd2],my_list[indexOfPwd2+1] = my_list[indexOfPwd2+1],my_list[indexOfPwd2]
Brent escribe el código el
0
for i in range(len(arr)):
    if l[-1] > l[i]:
        l[-1], l[i] = l[i], l[-1]
        break

Como resultado de esto, si el último elemento es mayor que el elemento en la posición i, ambos se intercambian.

ravi tanwar
fuente
-1

puedes usar por ejemplo:

>>> test_list = ['title', 'email', 'password2', 'password1', 'first_name',
                 'last_name', 'next', 'newsletter']
>>> reorder_func = lambda x: x.insert(x.index('password2'),  x.pop(x.index('password2')+1))
>>> reorder_func(test_list)
>>> test_list
... ['title', 'email', 'password1', 'password2', 'first_name', 'last_name', 'next', 'newsletter']
SmartElectron
fuente
-1

No soy un experto en python, pero podrías intentar: decir

i = (1,2)

res = lambda i: (i[1],i[0])
print 'res(1, 2) = {0}'.format(res(1, 2)) 

arriba daría o / p como:

res(1, 2) = (2,1)
lambzee
fuente
1
Eso no funciona sin conocer la posición de las teclas para intercambiar.
mikl