Eu tenho uma lista de seqüências de caracteres como esta:
X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
Y = [ 0, 1, 1, 0, 1, 2, 2, 0, 1 ]
Qual é a maneira mais curta de classificar X usando valores de Y para obter a seguinte saída?
["a", "d", "h", "b", "c", "e", "i", "f", "g"]
A ordem dos elementos com a mesma "chave" não importa. Posso recorrer ao uso de for
construções, mas estou curioso para saber se há uma maneira mais curta. Alguma sugestão?
Respostas:
Código mais curto
Exemplo:
De um modo geral
Explicado:
zip
os doislist
s.list
base nozip
usosorted()
.list
.Para obter mais informações sobre como definir \ use o
key
parâmetro, bem como asorted
função em geral, dê uma olhada nisso .fonte
Feche as duas listas, classifique-as e pegue as partes que deseja:
Combine-os para obter:
fonte
X
é uma lista destr
, mas tenha cuidado se houver uma possibilidade que<
não está definido para alguns pares de itens emX
, por exemplo - se alguns deles foramNone
AttributeError: 'zip' object has no attribute 'sort'
é o que estou obtendo a partir de agora.sorted(zip(...))
ainda deve funcionar, ou:them = list(zip(...)); them.sort()
Além disso, se você não se importa em usar matrizes numpy (ou na verdade já está lidando com matrizes numpy ...), aqui está outra solução interessante:
Encontrei-o aqui: http://scienceoss.com/sort-one-list-by-another-list/
fonte
sortedArray1= array1[array2.argsort()]
. E isso também facilita a classificação de várias listas por uma coluna específica de uma matriz 2D: por exemplo,sortedArray1= array1[array2[:,2].argsort()]
a classificação da matriz1 (que pode ter várias colunas) pelos valores da terceira coluna da matriz2.A solução mais óbvia para mim é usar a
key
palavra - chave arg.Observe que você pode reduzi-lo para uma linha, se desejar:
fonte
Na verdade, eu vim aqui procurando classificar uma lista por uma lista em que os valores correspondiam.
fonte
index
executará um (N) O pesquisa nolist_a
resultando em umO(N² log N)
tipo.more_itertools
possui uma ferramenta para classificar iterables em paralelo:Dado
Demo
fonte
Eu gosto de ter uma lista de índices classificados. Dessa forma, eu posso classificar qualquer lista na mesma ordem que a lista de fontes. Depois de ter uma lista de índices classificados, uma simples compreensão da lista fará o truque:
Observe que a lista de índice classificada também pode ser obtida usando
numpy.argsort()
.fonte
Outra alternativa, combinando várias das respostas.
Para trabalhar com python3:
fonte
zip, classifique pela segunda coluna, retorne a primeira coluna.
fonte
list(zip(*sorted(zip(X,Y), key=operator.itemgetter(1))))[0]
Uma linha rápida.
Digamos que você queira que a lista a corresponda à lista b.
Isso é útil quando é necessário solicitar uma lista menor com valores maiores. Supondo que a lista maior contenha todos os valores da lista menor, isso pode ser feito.
fonte
X
eY
?index
executará um (N) O pesquisa nolist_b
resultando em umO(N² log N)
tipo.Você pode criar um
pandas Series
, usando a lista principal comodata
e a outra lista comoindex
e, em seguida, basta classificar pelo índice:resultado:
fonte
Aqui está a resposta do Whatangs se você deseja obter as duas listas classificadas (python3).
Lembre-se de que Zx e Zy são tuplas. Também estou vagando se há uma maneira melhor de fazer isso.
Aviso: Se você executá-lo com listas vazias, ele trava.
fonte
Criei uma função mais geral, que classifica mais de duas listas com base em outra, inspirada na resposta de @ Whatang.
fonte
Para obter valores exclusivos presentes em
list2
Para encontrar o local do índice em
list2
A localização do índice
list2
é rastreada usandocur_loclist
[0, 3, 7, 1, 2, 4, 8, 5, 6]
fonte
Esta é uma pergunta antiga, mas algumas das respostas que vejo postadas não funcionam de fato porque
zip
não são programáveis. Outras respostas não se deram ao trabalho deimport operator
fornecer mais informações sobre este módulo e seus benefícios aqui.Existem pelo menos duas boas expressões para esse problema. Começando com a entrada de exemplo que você forneceu:
Usando o idioma " Decorar-Classificar-Undecorate "
Isso também é conhecido como Schwartzian_transform após R. Schwartz, que popularizou esse padrão em Perl nos anos 90:
Note-se que, neste caso,
Y
eX
são ordenados e comparados lexicographically. Ou seja, os primeiros itens (deY
) são comparados; e se forem iguais, os segundos itens (deX
) serão comparados e assim por diante. Isso pode criar instabilidade resultados menos que você inclua os índices da lista original da ordem lexicográfica para manter as duplicatas na ordem original.Usando o
operator
móduloIsso fornece um controle mais direto sobre como classificar a entrada, para que você possa obter estabilidade na classificação simplesmente indicando a chave específica a ser classificada. Veja mais exemplos aqui .
fonte