Eu tenho uma lista de listas:
[[12, 'tall', 'blue', 1],
[2, 'short', 'red', 9],
[4, 'tall', 'blue', 13]]
Se eu quisesse classificar por um elemento, digamos o elemento alto / baixo, eu poderia fazê-lo via s = sorted(s, key = itemgetter(1))
.
Se eu quisesse classificar por tanto alto / baixo e cor, eu poderia fazer o tipo duas vezes, uma para cada elemento, mas há uma maneira mais rápida?
sort
. Isto ésorted([(4, 2), (0, 3), (0, 1)]) == [(0, 1), (0, 3), (4, 2)]
.Respostas:
Uma chave pode ser uma função que retorna uma tupla:
Ou você pode conseguir o mesmo usando
itemgetter
(o que é mais rápido e evita uma chamada de função Python):E observe que aqui você pode usar em
sort
vez de usarsorted
e depois redesignar:fonte
-
de números inteiros)revrse=True
apenas ax[1]
isso é possível?s = sorted(s, key = operator.itemgetter(2))
depois pelo primários = sorted(s, key = operator.itemgetter(1), reverse=True)
Não é o ideal, mas funciona.-1
.Não tenho certeza se esse é o método mais pitonico ... Eu tinha uma lista de tuplas que precisavam classificar primeiro por valores inteiros decrescentes e segundo alfabeticamente. Isso exigia a reversão da classificação inteira, mas não da ordem alfabética. Aqui estava a minha solução: (em tempo real, em um exame, eu nem sabia que era possível "aninhar" funções classificadas)
fonte
b = sorted(a, key = lambda x: (-x[1], x[0]))
que é mais visível em quais critérios se aplicam primeiro. quanto à eficiência, não tenho certeza, alguém precisa cronometrar.Parece que você poderia usar a em
list
vez de atuple
. Isso se torna mais importante quando você pega atributos em vez de 'índices mágicos' de uma lista / tupla.No meu caso, eu queria classificar por vários atributos de uma classe, onde as chaves recebidas eram cadeias de caracteres. Eu precisava de classificação diferente em lugares diferentes e queria uma classificação padrão comum para a classe pai com a qual os clientes estavam interagindo; apenas tendo que substituir as 'chaves de classificação' quando eu realmente 'precisava', mas também de uma maneira que eu pudesse armazená-las como listas que a classe pudesse compartilhar
Então, primeiro eu defini um método auxiliar
então para usá-lo
Isso usará a função lambda gerada, classificará a lista
object.attrA
e, desde então,object.attrB
assumiráobject
um getter correspondente aos nomes de string fornecidos. E o segundo caso seria resolvido atéobject.attrC
entãoobject.attrA
.Isso também permite que você exponha potencialmente as opções de classificação externa a serem compartilhadas da mesma forma por um consumidor, um teste de unidade ou para que talvez lhe digam como desejam que a classificação seja feita para alguma operação em sua API, apenas para fornecer uma lista e não acoplando-os à sua implementação de back-end.
fonte
Vários anos atrasado para a festa, mas eu quero tanto espécie em 2 critérios e uso
reverse=True
. Caso alguém queira saber como, você pode colocar seus critérios (funções) entre parênteses:fonte
Aqui está uma maneira: Você basicamente reescreve sua função de classificação para obter uma lista de funções de classificação, cada função de classificação compara os atributos que você deseja testar, em cada teste de classificação, você olha e vê se a função cmp retorna um retorno diferente de zero nesse caso, interrompa e envie o valor de retorno. Você o chama chamando um Lambda de uma função de uma lista de Lambdas.
Sua vantagem é que ele passa os dados de maneira única, não como uma espécie anterior, como outros métodos. Outra coisa é que ele é ordenado, enquanto que o ordenado parece fazer uma cópia.
Usei-o para escrever uma função de classificação, que classifica uma lista de classes em que cada objeto está em um grupo e tem uma função de pontuação, mas você pode adicionar qualquer lista de atributos. Observe o uso não lambda, embora hackish, de um lambda para chamar um setter. A parte de classificação não funcionará para uma matriz de listas, mas a classificação funcionará.
Aqui está uma maneira de classificar uma lista de objetos
fonte