Ou, na prática, como posso classificar uma lista de dicionários por várias teclas?
Eu tenho uma lista de dictos:
b = [{u'TOT_PTS_Misc': u'Utley, Alex', u'Total_Points': 96.0},
{u'TOT_PTS_Misc': u'Russo, Brandon', u'Total_Points': 96.0},
{u'TOT_PTS_Misc': u'Chappell, Justin', u'Total_Points': 96.0},
{u'TOT_PTS_Misc': u'Foster, Toney', u'Total_Points': 80.0},
{u'TOT_PTS_Misc': u'Lawson, Roman', u'Total_Points': 80.0},
{u'TOT_PTS_Misc': u'Lempke, Sam', u'Total_Points': 80.0},
{u'TOT_PTS_Misc': u'Gnezda, Alex', u'Total_Points': 78.0},
{u'TOT_PTS_Misc': u'Kirks, Damien', u'Total_Points': 78.0},
{u'TOT_PTS_Misc': u'Worden, Tom', u'Total_Points': 78.0},
{u'TOT_PTS_Misc': u'Korecz, Mike', u'Total_Points': 78.0},
{u'TOT_PTS_Misc': u'Swartz, Brian', u'Total_Points': 66.0},
{u'TOT_PTS_Misc': u'Burgess, Randy', u'Total_Points': 66.0},
{u'TOT_PTS_Misc': u'Smugala, Ryan', u'Total_Points': 66.0},
{u'TOT_PTS_Misc': u'Harmon, Gary', u'Total_Points': 66.0},
{u'TOT_PTS_Misc': u'Blasinsky, Scott', u'Total_Points': 60.0},
{u'TOT_PTS_Misc': u'Carter III, Laymon', u'Total_Points': 60.0},
{u'TOT_PTS_Misc': u'Coleman, Johnathan', u'Total_Points': 60.0},
{u'TOT_PTS_Misc': u'Venditti, Nick', u'Total_Points': 60.0},
{u'TOT_PTS_Misc': u'Blackwell, Devon', u'Total_Points': 60.0},
{u'TOT_PTS_Misc': u'Kovach, Alex', u'Total_Points': 60.0},
{u'TOT_PTS_Misc': u'Bolden, Antonio', u'Total_Points': 60.0},
{u'TOT_PTS_Misc': u'Smith, Ryan', u'Total_Points': 60.0}]
e preciso usar uma classificação de várias chaves revertida por Total_Points, e não revertida por TOT_PTS_Misc
.
Isso pode ser feito no prompt de comando da seguinte forma:
a = sorted(b, key=lambda d: (-d['Total_Points'], d['TOT_PTS_Misc']))
Mas eu tenho que executar isso por meio de uma função, onde passo a lista e as chaves de classificação. Por exemplo def multikeysort(dict_list, sortkeys):
,.
Como a linha lambda pode ser usada para classificar a lista, para um número arbitrário de chaves que são passadas para a função multikeysort, e levar em consideração que as chaves de classificação podem ter qualquer número de chaves e aquelas que precisam de classificações invertidas serão identificadas com um '-' antes disso?
cmp()
não está disponível para Python3, então tive que defini-lo sozinho, conforme mencionado aqui: stackoverflow.com/a/22490617/398514cmp
palavra - chave, mas acmp()
função ainda é usada 4 linhas acima. Tentei com 3.2, 3.3, 3.4 e 3.5, todos falharam na chamada de função, porquecmp()
não está definido. O terceiro marcador aqui ( docs.python.org/3.0/whatsnew/3.0.html#ordering-comparisons ) menciona o tratamentocmp()
como desaparecido.Este artigo apresenta um bom resumo das várias técnicas para fazer isso. Se seus requisitos são mais simples do que "multi-chave bidirecional completa", dê uma olhada. Está claro que a resposta aceita e a postagem do blog que acabei de mencionar influenciaram um ao outro de alguma forma, embora eu não saiba em qual ordem.
No caso de o link morrer, aqui está uma sinopse muito rápida de exemplos não cobertos acima:
fonte
result = cmp(fn(left), fn(right))
Eu sei que esta é uma pergunta bastante antiga, mas nenhuma das respostas menciona que o Python garante uma ordem de classificação estável para suas rotinas de classificação como
list.sort()
esorted()
, o que significa que os itens comparados iguais mantêm sua ordem original.Isso significa que o equivalente a
ORDER BY name ASC, age DESC
(usando a notação SQL) para uma lista de dicionários pode ser feito assim:Observe como os itens são classificados primeiro pelo atributo "menor"
age
(decrescente) e, em seguida, pelo atributo "principal"name
, levando à ordem final correta.A reversão / inversão funciona para todos os tipos que podem ser solicitados, não apenas para números que você pode negar colocando um sinal de menos na frente.
E por causa do algoritmo Timsort usado em (pelo menos) CPython, isso é bastante rápido na prática.
fonte
fonte
some_string.split(",")
Eu uso o seguinte para classificar uma matriz 2d em várias colunas
Isso poderia ser estendido para funcionar em um número arbitrário de itens. Tendo a pensar que encontrar um padrão de acesso melhor para suas chaves classificáveis é melhor do que escrever um comparador sofisticado.
fonte
Tive um problema semelhante hoje - tive que classificar os itens do dicionário em valores numéricos decrescentes e em valores de string crescentes. Para resolver o problema das direções conflitantes, neguei os valores inteiros.
Aqui está uma variante da minha solução - conforme aplicável ao OP
Muito simples - e funciona perfeitamente
fonte
Demonstração:
A análise é um pouco frágil, mas pelo menos permite um número variável de espaços entre as chaves.
fonte
Como você já está confortável com lambda, aqui está uma solução menos prolixa.
fonte