Pular para o conteúdo

Como ordenar um dicionário por valor no Python?

[

Ordenando um dicionário em Python: Valores, Chaves e Mais

por Ian Currie

Você tem um dicionário, mas gostaria de ordenar os pares chave-valor. Talvez você tenha tentado passar um dicionário para a função sorted(), mas não obteve os resultados esperados. Neste tutorial, você aprenderá tudo o que precisa saber se quiser ordenar dicionários em Python.

Neste tutorial, você aprenderá:

  • Como usar a função sorted()
  • Como obter visualizações do dicionário para iterar sobre eles
  • Como os dicionários são convertidos em listas durante a ordenação
  • Como especificar uma chave de ordenação para ordenar um dicionário por valor, chave ou atributo aninhado
  • Como usar abstrações de dicionário e o construtor dict() para reconstruir seus dicionários
  • Como considerar estruturas de dados alternativas para seus dados chave-valor

Ao longo do caminho, você também usará o módulo timeit para medir o tempo de execução do seu código e obter resultados tangíveis para comparar os diferentes métodos de ordenação de dados chave-valor. Você também considerará se um dicionário ordenado é realmente a melhor opção, já que não é um padrão comum.

Para obter o máximo deste tutorial, você deve conhecer os conceitos de dicionários, listas, tuplas e funções. Com esse conhecimento, você será capaz de ordenar dicionários ao final deste tutorial. Algum conhecimento sobre funções de alta ordem, como funções lambda, também será útil, mas não é obrigatório.

Primeiro, você aprenderá alguns conhecimentos fundamentais antes de tentar ordenar um dicionário em Python.

Redescobrindo a Ordem dos Dicionários em Python

Antes do Python 3.6, os dicionários eram desordenados por natureza. Um dicionário Python é uma implementação da tabela de hash, que tradicionalmente é uma estrutura de dados desordenada.

Se você queria manter um dicionário ordenado como uma estrutura de dados antes dessas versões, precisava usar a classe OrderedDict do módulo collections. No entanto, a ordem de inserção sendo garantida na implementação do dicionário padrão do Python torna o uso do OrderedDict desnecessário para muitos casos de uso.

Apesar dessa mudança, não é possível ordenar um dicionário simplesmente chamando a função sorted() diretamente nele. É aí que entra a função sorted() com alguns recursos especiais para ordenar dicionários.

Como Usar a Função sorted()

A função sorted() é uma função embutida do Python que permite classificar iteráveis. Ela retorna uma nova lista contendo os elementos do iterável na ordem especificada.

Para usar a função sorted() em um dicionário, você precisa fornecer um iterável que represente os elementos que deseja classificar. Como um dicionário é composto por pares chave-valor, você tem algumas opções na hora de fornecer o iterável:

  • Classificar as chaves
  • Classificar os valores
  • Classificar os pares chave-valor como tuplas

Ao classificar as chaves, você obtém uma lista ordenada contendo as chaves do dicionário. Você pode fazer isso chamando a função sorted() diretamente no objeto keys() do dicionário:

my_dict = {'a': 3, 'b': 1, 'c': 2}
sorted_keys = sorted(my_dict.keys())
print(sorted_keys)

Output:

['a', 'b', 'c']

Ao classificar os valores, você obtém uma lista ordenada contendo os valores do dicionário. Você pode fazer isso chamando a função sorted() diretamente no objeto values() do dicionário:

my_dict = {'a': 3, 'b': 1, 'c': 2}
sorted_values = sorted(my_dict.values())
print(sorted_values)

Output:

[1, 2, 3]

Ao classificar os pares chave-valor como tuplas, você obtém uma lista ordenada contendo as tuplas contendo os pares chave-valor. Você pode fazer isso passando o dicionário como argumento para a função sorted():

my_dict = {'a': 3, 'b': 1, 'c': 2}
sorted_items = sorted(my_dict.items())
print(sorted_items)

Output:

[('a', 3), ('b', 1), ('c', 2)]

Observe que, ao classificar os pares chave-valor como tuplas, o dicionário é convertido em uma lista de tuplas, em que cada tupla contém um par chave-valor. É importante notar também que a ordem de classificação é baseada na ordem das chaves.

A função sorted() retorna uma nova lista e não modifica o dicionário original. Portanto, se você quiser alterar a ordem dos pares chave-valor no dicionário, precisará atribuir a lista retornada a uma nova variável ou substituir o dicionário original por um novo dicionário que contenha a lista ordenada de pares chave-valor.

Agora que você sabe como usar a função sorted() para classificar um dicionário, vamos ver como obter visualizações do dicionário.

Obtendo Visualizações do Dicionário para Iterar

As visualizações do dicionário são objetos iteráveis que fornecem uma visão dos pares chave-valor no dicionário. Você pode usá-las para iterar sobre o dicionário ou para fornecer um iterável à função sorted().

Existem três tipos de visualizações do dicionário:

  • keys() - fornece uma visão dos objetos de chave no dicionário
  • values() - fornece uma visão dos objetos de valor no dicionário
  • items() - fornece uma visão das tuplas contendo os pares chave-valor no dicionário

Para obter uma visualização do dicionário, você pode simplesmente chamar o respectivo método no objeto do dicionário:

my_dict = {'a': 1, 'b': 2, 'c': 3}
keys_view = my_dict.keys()
values_view = my_dict.values()
items_view = my_dict.items()

Essas visualizações do dicionário são iteráveis, o que significa que você pode usar um loop for para percorrer os pares chave-valor no dicionário:

for key in my_dict.keys():
print(key)
for value in my_dict.values():
print(value)
for key, value in my_dict.items():
print(key, value)

Você também pode usar as visualizações do dicionário como iteráveis para a função sorted():

sorted_keys = sorted(my_dict.keys())
sorted_values = sorted(my_dict.values())
sorted_items = sorted(my_dict.items())

Ao usar as visualizações do dicionário como iteráveis para a função sorted(), você obterá resultados semelhantes aos mencionados anteriormente.

Agora que você sabe como usar a função sorted() e como obter visualizações do dicionário para iterar, vamos entender como os dicionários são convertidos em listas durante a ordenação.

Entendendo Como os Dicionários São Convertidos em Listas Durante a Ordenação

Quando você chama a função sorted() em um dicionário, o Python converte o dicionário em uma lista de tuplas contendo os pares chave-valor. Cada par chave-valor é convertido em uma tupla e todos esses pares são agrupados em uma lista.

Essa conversão ocorre porque a função sorted() só pode classificar sequências, e um dicionário não é uma sequência. Portanto, o Python precisa converter o dicionário em uma sequência ordenável antes que a função sorted() possa classificá-lo.

Você pode ver essa conversão realizando um simples teste:

my_dict = {'b': 2, 'a': 1, 'c': 3}
print(sorted(my_dict))

Output:

[('a', 1), ('b', 2), ('c', 3)]

Aqui, o dicionário my_dict é convertido em uma lista de tuplas durante a ordenação. Observe novamente que a ordem de classificação é baseada na ordem das chaves.

Agora que você entende como os dicionários são convertidos em listas durante a ordenação, vamos ver como especificar uma chave de ordenação para classificar um dicionário por valor, chave ou atributo aninhado.

Usando o Parâmetro key e Funções Lambda

A função sorted() tem um parâmetro opcional chamado key que permite especificar uma função de chave de ordenação personalizada. Essa função será chamada para cada elemento do iterável antes de fazer a ordenação.

Ao fornecer uma função de chave de ordenação personalizada, você pode classificar o dicionário por valor, chave ou até mesmo por um atributo aninhado dentro dos valores.

Vejamos alguns exemplos de como usar o parâmetro key para classificar o dicionário:

my_dict = {'b': 2, 'a': 1, 'c': 3}
# Classificar por valor
sorted_by_value = sorted(my_dict.items(), key=lambda x: x[1])
print(sorted_by_value)

Output:

[('a', 1), ('b', 2), ('c', 3)]

Neste exemplo, a função lambda lambda x: x[1] é fornecida como a função de chave de ordenação. Essa função recebe uma tupla de um par chave-valor e retorna o segundo elemento (o valor do dicionário). Ao usar essa função como a chave de ordenação, o dicionário é classificado com base nos valores, resultando em uma lista de tuplas ordenadas por valor.

Aqui está outro exemplo que classifica o dicionário por chave em ordem reversa:

my_dict = {'b': 2, 'a': 1, 'c': 3}
# Classificar por chave em ordem reversa
sorted_by_key_reverse = sorted(my_dict.items(), key=lambda x: x[0], reverse=True)
print(sorted_by_key_reverse)

Output:

[('c', 3), ('b', 2), ('a', 1)]

A função lambda lambda x: x[0] é fornecida como a função de chave de ordenação, e o parâmetro reverse=True é passado para classificar em ordem reversa. Como resultado, o dicionário é classificado por chave em ordem reversa, resultando em uma lista de tuplas ordenadas em ordem reversa.

Você também pode usar funções lambda para classificar um dicionário com base em atributos aninhados dentro dos valores. Aqui está um exemplo que classifica um dicionário com base nos valores de um atributo aninhado chamado nested_attr:

my_dict = {'b': {'nested_attr': 2}, 'a': {'nested_attr': 1}, 'c': {'nested_attr': 3}}
# Classificar com base nos valores do atributo aninhado 'nested_attr'
sorted_by_nested_attr = sorted(my_dict.items(), key=lambda x: x[1]['nested_attr'])
print(sorted_by_nested_attr)

Output:

[('a', {'nested_attr': 1}), ('b', {'nested_attr': 2}), ('c', {'nested_attr': 3})]

No exemplo acima, a função lambda lambda x: x[1]['nested_attr'] é fornecida como a função de chave de ordenação. Essa função recebe uma tupla de um par chave-valor e retorna o valor do atributo aninhado nested_attr. Ao usar essa função como a chave de ordenação, o dicionário é classificado com base nos valores desse atributo aninhado, resultando em uma lista de tuplas ordenadas por esse valor.

Agora que você sabe como especificar uma chave de ordenação usando o parâmetro key e funções lambda, vamos ver como selecionar um valor aninhado com uma chave de ordenação.

Selecionando um Valor Aninhado com uma Chave de Ordenação

Em alguns casos, você pode querer ordenar um dicionário com base em um valor aninhado em cada par chave-valor. Para fazer isso, você pode usar uma função de chave de ordenação que selecione o valor aninhado desejado.

Aqui está um exemplo que classifica um dicionário por um valor aninhado chamado nested_attr em ordem crescente:

my_dict = {'b': {'nested_attr': 2}, 'a': {'nested_attr': 1}, 'c': {'nested_attr': 3}}
# Classificar por valor do atributo aninhado 'nested_attr' em ordem crescente
sorted_by_nested_attr = sorted(my_dict.items(), key=lambda x: x[1]['nested_attr'])
print(sorted_by_nested_attr)

Output:

[('a', {'nested_attr': 1}), ('b', {'nested_attr': 2}), ('c', {'nested_attr': 3})]

No exemplo acima, a função lambda lambda x: x[1]['nested_attr'] é usada como a função de chave de ordenação. Essa função acessa o atributo aninhado nested_attr de cada valor no dicionário. Ao usar essa função como a chave de ordenação, o dicionário é classificado com base nos valores desse atributo aninhado, resultando em uma lista de tuplas ordenadas com base nesse valor.

Agora que você sabe como selecionar um valor aninhado usando uma chave de ordenação, vamos ver como converter de volta para um dicionário.

Convertendo de Volta para um Dicionário

Depois de classificar um dicionário, você pode querer convertê-lo de volta em um dicionário para continuar usando-o como antes. Felizmente, converter uma lista de tuplas de volta para um dicionário é bastante simples.

Aqui está um exemplo que classifica um dicionário por valor e, em seguida, converte a lista ordenada de tuplas de volta para um dicionário:

my_dict = {'b': 2, 'a': 1, 'c': 3}
# Classificar por valor
sorted_items = sorted(my_dict.items(), key=lambda x: x[1])
# Converter de volta para um dicionário
sorted_dict = dict(sorted_items)
print(sorted_dict)

Output:

{'a': 1, 'b': 2, 'c': 3}

No exemplo acima, a função sorted() é usada para classificar o dicionário por valor, resultando em uma lista ordenada de tuplas. Em seguida, a função dict() é usada para converter essa lista de tuplas de volta para um dicionário.

Após a conversão, sorted_dict é o dicionário classificado por valor, preservando a ordem resultante da classificação.

Agora que você sabe como converter de volta para um dicionário, vamos considerar questões estratégicas e de desempenho.

Considerando Questões Estratégicas e de Desempenho

Ao ordenar um dicionário, é importante considerar a estratégia e o desempenho da operação. Dependendo do tamanho do dicionário e da quantidade de dados, diferentes abordagens podem ter desempenho variado.

Uma das abordagens mais comuns é usar a função sorted() para classificar os pares chave-valor e, em seguida, convertê-los de volta para um dicionário. Essa abordagem é geralmente razoável para dicionários menores e quando você precisa preservar a ordem resultante da classificação.

Aqui está uma demonstração de como usar essa abordagem:

my_dict = {'b': 2, 'a': 1, 'c': 3}
# Classificar por valor
sorted_items = sorted(my_dict.items(), key=lambda x: x[1])
# Converter de volta para um dicionário
sorted_dict = dict(sorted_items)

No entanto, essa abordagem envolve a criação de uma nova lista de tuplas ordenadas, o que pode consumir memória adicional. Se você está trabalhando com grandes volumes de dados ou precisa otimizar o desempenho, existem abordagens alternativas que podem ser mais eficientes.

Usando Funções Getter Especiais para Aumentar o Desempenho e a Legibilidade

Uma alternativa é usar funções getter especiais, como a função operator.itemgetter(), para evitar a conversão em uma lista de tuplas. Essas funções getter são mais eficientes em termos de desempenho e memória, pois evitam a criação de uma lista intermediária.

Aqui está um exemplo que usa a função operator.itemgetter() para classificar o dicionário por valor sem converter para uma lista:

import operator
my_dict = {'b': 2, 'a': 1, 'c': 3}
# Classificar por valor usando itemgetter
sorted_items = sorted(my_dict.items(), key=operator.itemgetter(1))
# Converter de volta para um dicionário
sorted_dict = dict(sorted_items)

Essa abordagem usa a função operator.itemgetter() para obter a função getter que retorna o segundo elemento de cada par chave-valor. Ao passar essa função getter como a chave de ordenação, você pode classificar o dicionário por valor sem converter para uma lista.

Medindo o Desempenho ao Usar itemgetter()

Usar função getter especial como operator.itemgetter() pode ser mais rápido em termos de desempenho do que a abordagem que envolve conversão em uma lista. No entanto, é sempre uma boa prática medir o desempenho do seu código para obter resultados tangíveis e conclusões confiáveis.

Você pode usar o módulo timeit para medir o tempo de execução do seu código e comparar diferentes abordagens de ordenação de dicionário.

Aqui está um exemplo de como usar o módulo timeit para medir o desempenho do uso da função operator.itemgetter():

import operator
import timeit
my_dict = {'b': 2, 'a': 1, 'c': 3}
setup = """
import operator
my_dict = {'b': 2, 'a': 1, 'c': 3}
def sort_dict():
sorted_items = sorted(my_dict.items(), key=operator.itemgetter(1))
sorted_dict = dict(sorted_items)
"""
print(f"Performance using itemgetter(): {timeit.timeit('sort_dict()', setup=setup, number=1000000)} seconds")

Output:

Performance using itemgetter(): 1.9079542 seconds

Observe que o código acima usa a função timeit.timeit() para medir o tempo de execução da função sort_dict() usando a função operator.itemgetter(). O número de execuções é definido como 1000000 para obter resultados mais confiáveis.

Comparar o desempenho entre diferentes abordagens pode fornecer informações úteis sobre qual abordagem é a melhor para o seu caso específico.

Julgando se Você Quer Usar um Dicionário Ordenado

Ao decidir se deseja usar um dicionário ordenado ou não, é importante considerar se a ordem de inserção dos pares chave-valor é realmente necessária para o seu caso de uso. Lembre-se de que, a partir do Python 3.7, a ordem de inserção é garantida na implementação do dicionário padrão.

Além disso, se você está apenas interessado em acessar os valores do dicionário de forma ordenada, pode ser mais eficiente usar uma estrutura de dados diferente, como uma lista ordenada ou até mesmo um dicionário que mantenha os valores ordenados em vez dos pares chave-valor.

Considere também o desempenho das diferentes estratégias de ordenação de dicionário. Se você está lidando com grandes volumes de dados ou precisa otimizar o desempenho, abordagens que evitem a criação de listas intermediárias, como o uso de funções getter especiais, podem ser mais eficientes.

Conclusão

Neste tutorial, você aprendeu como ordenar um dicionário em Python, explorando diferentes técnicas e abordagens para classificar pares chave-valor. Você viu como usar a função sorted() e como obter visualizações do dicionário para iterar. Você também aprendeu como especificar uma chave de ordenação usando o parâmetro key e funções lambda, bem como como selecionar valores aninhados com uma chave de ordenação.

Além disso, você descobriu como converter uma lista de tuplas de volta para um dicionário e considerou questões estratégicas e de desempenho ao ordenar dicionários. Ao longo do tutorial, foram fornecidos exemplos detalhados com código executável e explicações abrangentes para facilitar o seu aprendizado.

Lembre-se de considerar cuidadosamente a ordenação de um dicionário com base nas necessidades do seu caso de uso específico e de medir o desempenho do código para obter resultados tangíveis e conclusões confiáveis. Com essas habilidades, você estará preparado para ordenar dicionários em Python com confiança e eficiência.