Eu tenho uma lista de dicionários e quero que cada item seja classificado por valores de propriedade específicos.
Leve em consideração a matriz abaixo,
[{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]
Quando ordenado por name
, deve tornar-se
[{'name':'Bart', 'age':10}, {'name':'Homer', 'age':39}]
[{'name':'Bart', 'age':10, 'note':3},{'name':'Homer','age':10,'note':2},{'name':'Vasile','age':20,'note':3}]
E para usar:from operator import itemgetter newlist = sorted(old_list, key=itemgetter(-'note','name')
EDIT: Testado e está funcionando, mas não sei como anotar DESC e nomear ASC.Respostas:
Pode parecer mais limpo usando uma chave em vez de um cmp:
ou como JFSebastian e outros sugeriram,
Para completar (como indicado nos comentários de fitzgeraldsteele), adicione
reverse=True
à classificação decrescentefonte
itemgetter(i)
ondei
está o índice do elemento de tupla para classificar.itemgetter
aceita mais de um argumento:itemgetter(1,2,3)
é uma função que retorna uma tupla comoobj[1], obj[2], obj[3]
, para que você possa usá-la para fazer classificações complexas.Para classificar a lista de dicionários por key = 'name':
Para classificar a lista de dicionários por key = 'age':
fonte
key=lambda k: (k['name'], k['age'])
,. (oukey=itemgetter('name', 'age')
) tuplascmp
comparará cada elemento por vez. é brilhante demais.key
argumento opcional paralist.sort()
não é descrito. Alguma idéia de onde encontrar isso?list
e amigos.my_list
agora será o que você quer.(3 anos depois) Editado para adicionar:
O novo
key
argumento é mais eficiente e mais organizado. Uma resposta melhor agora se parece com:... o lambda é, na IMO, mais fácil de entender do que
operator.itemgetter
, mas YMMV.fonte
Se você deseja classificar a lista por várias chaves, faça o seguinte:
É um tanto tolo, pois depende da conversão dos valores em uma única representação de string para comparação, mas funciona como esperado para números incluindo negativos (embora você precise formatar sua string adequadamente com zero, se estiver usando números)
fonte
'key' é usado para classificar por um valor arbitrário e 'itemgetter' define esse valor para o atributo 'name' de cada item.
fonte
fonte
Eu acho que você quis dizer:
Isso seria classificado assim:
fonte
Você pode usar uma função de comparação personalizada ou pode transmitir uma função que calcula uma chave de classificação personalizada. Isso geralmente é mais eficiente, pois a chave é calculada apenas uma vez por item, enquanto a função de comparação seria chamada muitas mais vezes.
Você poderia fazer assim:
Mas a biblioteca padrão contém uma rotina genérica para obter itens de objetos arbitrários:
itemgetter
. Então tente isso:fonte
Usando a transformação schwartziana do Perl,
Faz
dá
Mais sobre a transformação de Perl Schwartzian
fonte
key=
para.sort
desde 2,4, que é ano de 2004, ele faz o Schwartziana transformar dentro do código de classificação, no C; portanto, esse método é útil apenas no Pythons 2.0-2.3. todos com mais de 12 anos.Você precisa implementar sua própria função de comparação que comparará os dicionários pelos valores das chaves de nome. Veja Classificando o Mini-HOW TO do PythonInfo Wiki
fonte
em algum momento precisamos usar,
lower()
por exemplofonte
Aqui está a solução geral alternativa - ela classifica os elementos do ditado por chaves e valores. A vantagem disso - não é necessário especificar chaves, e ainda funcionaria se algumas chaves estiverem ausentes em alguns dicionários.
fonte
O uso do pacote pandas é outro método, embora o tempo de execução em larga escala seja muito mais lento que os métodos mais tradicionais propostos por outros:
Aqui estão alguns valores de referência para uma lista minúscula e uma lista grande (100k +) de dictos:
fonte
Se você não precisa do original
list
dedictionaries
, você pode modificá-lo no local comsort()
método utilizando uma função chave personalizado.Função chave:
A
list
ser classificado:Classificando-o no local:
Se você precisar do original
list
, chame asorted()
função que passa por elelist
e a função da tecla e atribua o retornado classificadolist
a uma nova variável:Impressão
data_one
enew_data
.fonte
Digamos que eu tenho um dicionário
D
com elementos abaixo. Para classificar, use o argumento-chave em ordenado para passar a função personalizada como abaixo:Veja isso .
fonte
Eu tenho sido um grande fã de filtro w / lambda no entanto, não é a melhor opção se você considerar a complexidade do tempo
Primeira opção
Segunda opçao
Comparação rápida de tempos de execução
fonte
Se o desempenho é uma preocupação, eu usaria, em
operator.itemgetter
vez delambda
as funções internas, executarem mais rapidamente que as funções artesanais. Aitemgetter
função parece executar aproximadamente 20% mais rápido do que comlambda
base nos meus testes.Em https://wiki.python.org/moin/PythonSpeed :
Aqui está uma comparação de triagem velocidade usando
lambda
vsitemgetter
.Ambas as técnicas classificam a lista na mesma ordem (verificada pela execução da instrução final no bloco de código), mas uma é um pouco mais rápida.
fonte
Você pode usar o seguinte código
fonte