Como mudar a posição de dois itens em uma lista Python?

208

Não consegui encontrar uma boa solução para esse problema na rede (provavelmente porque switch, position, list e Python são todas essas palavras sobrecarregadas).

É bastante simples - eu tenho esta lista:

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

Eu gostaria de mudar de posição 'password2'e 'password1'- sem saber a posição exata, apenas que eles estão próximos um do outro e password2são os primeiros.

Consegui isso com algumas assinaturas de listas bastante longas, mas imaginei que seria possível criar algo um pouco mais elegante?

mikl
fonte
O seu problema é a eficiência de tentar encontrar 'password2' na lista? 'Password1' pode vir antes de 'password2'? Existe alguma complexidade aqui que não aparece na sua pergunta original? Caso contrário, concordo com @unwind.
Brent escreve código
3
Você deve postar o que tem - estou curioso sobre o que você quer dizer com "subscrição de listas bastante demorada".
Samtregar 22/03
Algo parecido com index1 = index ('password1'); index2 = index ('senha2'); order = order [: index2] .append (order [index1]). append (order [index2]). append (order [index1 + 1:]); espalhe em mais algumas linhas. Bonito, não.
Mikl 22/03/10

Respostas:

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

A troca simples do Python é assim:

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

Agora tudo o que você precisa fazer é descobrir o que ié e isso pode ser feito facilmente com index:

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

Dadas as suas especificações, eu usaria a atribuição de fatias:

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

O lado direito da atribuição da fatia é uma "fatia invertida" e também pode ser escrito:

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

se você achar isso mais legível, como muitos acham.

Alex Martelli
fonte
Por que isso não está funcionando se você deseja alternar título e email, o primeiro elemento com o segundo?
Luigi Tiburzi 26/10
Desculpe eu compreendo agora, não há elementos no i-1 assim uma lista vazia é retornado
Luigi Tiburzi
7

Como pode ser mais longo do que

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

Isso é apenas uma troca simples usando armazenamento temporário.

descontrair
fonte
13
Se você quer ser realmente "pitonico", também pode fazer isso também:my_list[indexOfPwd2],my_list[indexOfPwd2+1] = my_list[indexOfPwd2+1],my_list[indexOfPwd2]
Brent Writes Code
0
for i in range(len(arr)):
    if l[-1] > l[i]:
        l[-1], l[i] = l[i], l[-1]
        break

como resultado, se o último elemento for maior que o elemento na posição i, os dois serão trocados.

Ravi Tanwar
fonte
-1

você pode usar, por exemplo:

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

Eu não sou especialista em python, mas você pode tentar: digamos

i = (1,2)

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

acima daria o / p como:

res(1, 2) = (2,1)
lambzee
fonte
1
Isso não funciona sem conhecer a posição das chaves a serem trocadas.
mikl