Digamos que eu tenha duas listas:
list1 = [3, 2, 4, 1, 1]
list2 = ['three', 'two', 'four', 'one', 'one2']
Se eu executar list1.sort()
, ele será ordenado, [1,1,2,3,4]
mas existe uma maneira de list2
sincronizar também (para que eu possa dizer que o item 4
pertence 'three'
)? Portanto, o resultado esperado seria:
list1 = [1, 1, 2, 3, 4]
list2 = ['one', 'one2', 'two', 'three', 'four']
Meu problema é que tenho um programa bastante complexo que funciona bem com listas, mas preciso começar a referenciar alguns dados. Sei que esta é uma situação perfeita para dicionários, mas estou tentando evitar dicionários no meu processamento porque preciso classificar os valores das chaves (se devo usar dicionários, sei como usá-los).
Basicamente, a natureza desse programa é que os dados são apresentados em uma ordem aleatória (como acima), preciso classificá-los, processá-los e enviar os resultados (a ordem não importa, mas os usuários precisam saber qual resultado pertence a qual chave). Pensei em colocá-lo em um dicionário primeiro e, em seguida, em uma lista de classificação, mas eu não teria como diferenciar itens com o mesmo valor se a ordem não for mantida (pode ter um impacto ao comunicar os resultados aos usuários). Então, idealmente, depois de obter as listas, prefiro descobrir uma maneira de classificar as duas listas. Isso é possível?
Respostas:
Uma abordagem clássica para esse problema é usar o idioma "decorar, classificar, não decorar", que é especialmente simples usando a função interna do python
zip
:Obviamente, essas não são mais listas, mas são facilmente remediadas, se isso importa:
Vale a pena notar que o exposto acima pode sacrificar a velocidade pela concisão; a versão local, que ocupa três linhas, é um pouco mais rápida na minha máquina para pequenas listas:
Por outro lado, para listas maiores, a versão em uma linha pode ser mais rápida:
Como aponta o Quantum7, a sugestão do JSF ainda é um pouco mais rápida, mas provavelmente só será um pouco mais rápida, porque o Python usa o mesmo idioma DSU internamente para todos os tipos de chaves. Está acontecendo um pouco mais perto do metal nu. (Isso mostra o quão otimizadas
zip
são as rotinas!)Eu acho que a
zip
abordagem baseada é mais flexível e um pouco mais legível, então eu prefiro.fonte
*
operador faz argumento desembalar ,zip(*x)
tem a propriedade interessante de que é o seu próprio inverso:l = [(1, 2), (3, 4)]; list(zip(*zip(*l))) == l
retornaTrue
. É efetivamente um operador de transposição.zip()
por si só é o mesmo operador, mas assume que você desempacotou a sequência de entrada manualmente.Você pode classificar índices usando valores como chaves:
Para obter listas classificadas com índices classificados:
No seu caso, você não deveria ter
list1
,list2
mas uma única lista de pares:É fácil de criar; é fácil classificar em Python:
Classifique apenas pelo primeiro valor:
fonte
list()
em torno demap()
se você gostaria de usar esse código em Python 3.sorted_list1 = list(map(list1.__getitem__, indexes))
um poderia fazersorted_list1 = [list1[i] for i in indexes]
.Eu tenho usado a resposta dada por remetente por um longo tempo até que eu descobri
np.argsort
. Aqui está como isso funciona.Acho essa solução mais intuitiva e funciona muito bem. O desempenho:
Embora
np.argsort
não seja o mais rápido, acho mais fácil de usar.fonte
TypeError: only integer arrays with one element can be converted to an index
(Python 2.7.6, numpy 1.8.2). Para corrigi-lo, list1 e list2 devem ser declaradas como matrizes numpy.np.argsort
não tente converter para umnp.array
internamente.Transformação Schwartziana . A classificação interna do Python é estável, portanto os dois
1
s não causam problemas.fonte
A respeito:
fonte
Você pode usar as funções
zip()
esort()
para fazer isso:Espero que isto ajude
fonte
Você pode usar o argumento chave no método classificado (), a menos que tenha dois mesmos valores na lista2.
O código é fornecido abaixo:
Classifica list2 de acordo com os valores correspondentes na lista1, mas certifique-se de que, ao usá-lo, dois valores na lista2 não sejam avaliados porque a função list.index () fornece o primeiro valor
fonte
Uma maneira é rastrear para onde cada índice vai, classificando a identidade [0,1,2, .. n]
Isso funciona para qualquer número de listas.
Em seguida, mova cada item para sua posição. Usar emendas é o melhor.
Observe que poderíamos ter iterado as listas sem sequer classificá-las:
fonte
Se você estiver usando numpy, poderá usar
np.argsort
para obter os índices classificados e aplicá-los à lista. Isso funciona para qualquer número de lista que você deseja classificar.fonte
uma solução algorítmica:
Saídas:
->
Velocidade de saída:0.2s
fonte
Outra abordagem para manter a ordem de uma lista de cadeias ao classificar em outra lista é a seguinte:
resultado
fonte
Gostaria de expandir a resposta do open jfs , que funcionou muito bem para o meu problema: classificar duas listas por uma terceira lista decorada :
Podemos criar nossa lista decorada de qualquer maneira, mas neste caso a criaremos a partir dos elementos de uma das duas listas originais que queremos classificar:
Agora podemos aplicar a solução do jfs para classificar nossas duas listas pela terceira
Edit: Ei pessoal, eu fiz um post sobre isso, confira se você quiser :) 🐍🐍🐍
fonte
fonte