Pular para o conteúdo

Como classificar um dicionário no Python

CodeMDD.io

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

por Ian Currie

Você possui um dicionário, mas gostaria de ordenar os pares de 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á:

  • Revisar como usar a função sorted()
  • Aprender como obter visualizações do dicionário para iterar
  • Entender como os dicionários são convertidos em listas durante a ordenação
  • Aprender como especificar uma chave de ordenação para ordenar um dicionário por valor, chave ou atributo aninhado
  • Revisar as compreensões de dicionário e o construtor dict() para reconstruir seus dicionários
  • Considerar estruturas de dados alternativas para seus dados de 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, pois não é um padrão particularmente comum.

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

Redescobrindo a Ordem de um Dicionário em Python

Se você deseja manter um dicionário ordenado como uma estrutura de dados antes do Python 3.6, precisaria usar a classe OrderedDict do módulo collections. No entanto, a partir do Python 3.7, você pode simplesmente usar um dicionário padrão para manter a ordem de inserção.

Entendendo o Que Significa Ordenar um Dicionário

Quando você diz que deseja ordenar um dicionário em Python, isso pode ter dois significados diferentes:

  1. Ordenar pelos valores do dicionário em uma ordem ascendente ou descendente.
  2. Ordenar pelas chaves do dicionário em uma ordem ascendente ou descendente.

A ordem pela qual você deseja ordenar o dicionário irá determinar a abordagem que você deve usar. Vamos dar uma olhada em como realizar cada tipo de ordenação.

Ordenando Dicionários em Python

Usando a função sorted()

A maneira mais simples de ordenar um dicionário é usando a função sorted(). Esta função retorna uma nova lista contendo todos os itens do dicionário, ordenados com base nas chaves ou valores.

Vamos começar ordenando um dicionário pela chave em ordem ascendente. Suponha que temos o seguinte dicionário:

dicionario = {"apple": 5, "banana": 2, "cherry": 3, "date": 1}

Para ordená-lo pela chave, podemos fazer o seguinte:

dicionario_ordenado = sorted(dicionario.items())

Isso retornará uma lista contendo os pares de chave-valor do dicionário ordenados pela chave em ordem ascendente:

[('apple', 5), ('banana', 2), ('cherry', 3), ('date', 1)]

Se você quiser ordenar o dicionário pela chave em ordem descendente, poderá usar o parâmetro reverse=True na função sorted():

dicionario_ordenado = sorted(dicionario.items(), reverse=True)

Isso retornará a lista de pares de chave-valor ordenados pela chave em ordem descendente:

[('date', 1), ('cherry', 3), ('banana', 2), ('apple', 5)]

Para ordenar o dicionário pelos valores em ordem ascendente, podemos usar o parâmetro key na função sorted() e fornecer uma função lambda para especificar que queremos ordenar pelos valores:

dicionario_ordenado = sorted(dicionario.items(), key=lambda x: x[1])

Isso retornará a lista de pares de chave-valor ordenados pelos valores em ordem ascendente:

[('date', 1), ('banana', 2), ('cherry', 3), ('apple', 5)]

Da mesma forma, se quisermos ordenar pelo valores em ordem descendente, podemos usar o parâmetro key com uma função lambda e o parâmetro reverse=True:

dicionario_ordenado = sorted(dicionario.items(), key=lambda x: x[1], reverse=True)

Isso retornará a lista de pares de chave-valor ordenados pelos valores em ordem descendente:

[('apple', 5), ('cherry', 3), ('banana', 2), ('date', 1)]

Obtendo Chaves, Valores ou Ambos de um Dicionário

Antes de prosseguirmos para outras maneiras de ordenar dicionários, é útil entender como obter as chaves, valores ou ambos de um dicionário.

Se você quiser obter todas as chaves de um dicionário, pode usar o método keys():

chaves = dicionario.keys()

Isso retornará um objeto de visualização das chaves do dicionário. Para convertê-lo em uma lista, você pode fazer o seguinte:

chaves = list(dicionario.keys())

Da mesma forma, se você quiser obter todos os valores do dicionário, pode usar o método values():

valores = dicionario.values()

Para convertê-lo em uma lista, você pode fazer:

valores = list(dicionario.values())

Se você quiser obter tanto as chaves quanto os valores do dicionário, pode usar o método items():

items = dicionario.items()

Este método retorna uma visualização do dicionário como uma sequência de pares de chave-valor. Para converter isso em uma lista, você pode fazer:

items = list(dicionario.items())

Agora que você sabe como obter as chaves, valores ou ambos de um dicionário, podemos prosseguir para outras maneiras de ordenar dicionários em Python.

Entendendo Como o Python Ordena Tuplas

Ao usar a função sorted() para ordenar um dicionário, você pode ter notado que os pares de chave-valor são considerados como tuplas e ordenados com base nas tuplas resultantes.

Entender como o Python ordena tuplas é importante para entender como a função sorted() funciona com dicionários.

Por padrão, o Python compara tuplas item a item: primeiro compara o primeiro item, depois o segundo item, e assim por diante, até que uma diferença seja encontrada ou todos os itens sejam comparados.

Portanto, quando você usa a função sorted() em um dicionário, as tuplas geradas são comparadas item a item. Por exemplo, se você ordenar um dicionário pela chave em ordem ascendente, o Python primeiro compara as chaves e, em seguida, compara os valores caso as chaves sejam iguais.

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

O parâmetro key da função sorted() permite que você especifique uma função que será usada como chave de ordenação. Isso é útil quando você deseja ordenar um dicionário por um valor específico, como o valor da chave ou um atributo aninhado.

Você pode usar uma função lambda para criar uma função temporária e usá-la como chave de ordenação. Vamos dar uma olhada em alguns exemplos.

Suponha que você tenha o seguinte dicionário de carros com seus respectivos preços:

carros = {"BMW": 50000, "Audi": 60000, "Mercedes": 55000, "Lexus": 45000}

Se você deseja ordenar esse dicionário pelos preços dos carros em ordem ascendente, você pode fazer o seguinte:

carros_ordenados = sorted(carros.items(), key=lambda x: x[1])

Isso retornará a lista de pares de chave-valor ordenados pelos preços em ordem ascendente:

[('Lexus', 45000), ('BMW', 50000), ('Mercedes', 55000), ('Audi', 60000)]

Da mesma forma, se você deseja ordenar pelo preço dos carros em ordem descendente, você pode fazer:

carros_ordenados = sorted(carros.items(), key=lambda x: x[1], reverse=True)

Isso retornará a lista de pares de chave-valor ordenados pelos preços em ordem descendente:

[('Audi', 60000), ('Mercedes', 55000), ('BMW', 50000), ('Lexus', 45000)]

Você também pode usar uma função lambda para especificar um atributo aninhado como chave de ordenação. Vamos supor que você tenha o seguinte dicionário de produtos com seus respectivos preços em diferentes moedas:

produtos = {
"banana": {"USD": 1.5, "EUR": 1.3, "GBP": 1.1},
"laranja": {"USD": 2, "EUR": 1.8, "GBP": 1.6},
"maçã": {"USD": 1.8, "EUR": 1.6, "GBP": 1.4}
}

Se você deseja ordenar esse dicionário pelas moedas em ordem ascendente, você pode fazer o seguinte:

produtos_ordenados = sorted(produtos.items(), key=lambda x: x[1]["GBP"])

Isso retornará a lista de pares de chave-valor ordenados pelas moedas em ordem ascendente:

[('banana', {'USD': 1.5, 'EUR': 1.3, 'GBP': 1.1}), ('maçã', {'USD': 1.8, 'EUR': 1.6, 'GBP': 1.4}), ('laranja', {'USD': 2, 'EUR': 1.8, 'GBP': 1.6})]

Da mesma forma, se você deseja ordenar pelas moedas em ordem descendente, você pode fazer:

produtos_ordenados = sorted(produtos.items(), key=lambda x: x[1]["GBP"], reverse=True)

Isso retornará a lista de pares de chave-valor ordenados pelas moedas em ordem descendente:

[('laranja', {'USD': 2, 'EUR': 1.8, 'GBP': 1.6}), ('maçã', {'USD': 1.8, 'EUR': 1.6, 'GBP': 1.4}), ('banana', {'USD': 1.5, 'EUR': 1.3, 'GBP': 1.1})]

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

Às vezes, você deseja ordenar um dicionário com base em um valor aninhado em vez de usar a chave ou o valor diretamente. Nesses casos, você pode usar uma função lambda no parâmetro key para selecionar o valor aninhado que deseja usar como chave de ordenação.

Vamos supor que você tenha o seguinte dicionário que armazena informações sobre alunos e suas notas em diferentes disciplinas:

alunos = {
"Alice": {"Matemática": 90, "Física": 85, "Química": 95},
"Bob": {"Matemática": 80, "Física": 75, "Química": 90},
"Charlie": {"Matemática": 95, "Física": 90, "Química": 85}
}

Se você deseja ordenar esse dicionário pela nota de Matemática em ordem ascendente, você pode fazer o seguinte:

alunos_ordenados = sorted(alunos.items(), key=lambda x: x[1]["Matemática"])

Isso retornará a lista de pares de chave-valor ordenados pela nota de Matemática em ordem ascendente:

[('Bob', {'Matemática': 80, 'Física': 75, 'Química': 90}), ('Alice', {'Matemática': 90, 'Física': 85, 'Química': 95}), ('Charlie', {'Matemática': 95, 'Física': 90, 'Química': 85})]

Da mesma forma, se você deseja ordenar pela nota de Matemática em ordem descendente, você pode fazer:

alunos_ordenados = sorted(alunos.items(), key=lambda x: x[1]["Matemática"], reverse=True)

Isso retornará a lista de pares de chave-valor ordenados pela nota de Matemática em ordem descendente:

[('Charlie', {'Matemática': 95, 'Física': 90, 'Química': 85}), ('Alice', {'Matemática': 90, 'Física': 85, 'Química': 95}), ('Bob', {'Matemática': 80, 'Física': 75, 'Química': 90})]

Convertendo de Volta para um Dicionário

Até agora, vimos como ordenar um dicionário, mas o resultado foi uma lista de pares de chave-valor. Se você deseja reconstruir o dicionário com base na ordenação, pode usar as compreensões de dicionário ou o construtor dict().

Vamos supor que você tenha a seguinte lista de pares de chave-valor ordenados por chave em ordem ascendente:

dicionario_ordenado = [('apple', 5), ('banana', 2), ('cherry', 3), ('date', 1)]

Para reconstruir o dicionário original, você pode usar uma compreensão de dicionário da seguinte maneira:

dicionario = {chave: valor for chave, valor in dicionario_ordenado}

Isso retornará o seguinte dicionário:

{'apple': 5, 'banana': 2, 'cherry': 3, 'date': 1}

Da mesma forma, você pode usar o construtor dict() com a lista de pares de chave-valor:

dicionario = dict(dicionario_ordenado)

Isso também retornará o seguinte dicionário:

{'apple': 5, 'banana': 2, 'cherry': 3, 'date': 1}

Agora você sabe como reconstruir um dicionário a partir de uma lista de pares de chave-valor ordenados.

Considerando Questões Estratégicas e de Desempenho

Ao trabalhar com dicionários ordenados em Python, é importante considerar questões estratégicas e de desempenho.

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

Às vezes, a função que você passa para o parâmetro key da função sorted() pode exigir um cálculo complexo para obter o valor desejado. Nesses casos, usar funções getter especiais, como itemgetter() ou attrgetter() do módulo operator, pode ser mais eficiente e legível.

Por exemplo, vamos supor que você tenha o seguinte dicionário de produtos com seus respectivos preços:

produtos = {"apple": {"USD": 2, "EUR": 1.8, "GBP": 1.6}, "banana": {"USD": 1.5, "EUR": 1.3, "GBP": 1.1}}

Se você deseja ordenar esse dicionário pelos preços em dólares em ordem ascendente, pode fazer o seguinte:

from operator import itemgetter
produtos_ordenados = sorted(produtos.items(), key=itemgetter(1, "USD"))

Isso retornará a lista de pares de chave-valor ordenados pelos preços em dólares em ordem ascendente:

[('banana', {'USD': 1.5, 'EUR': 1.3, 'GBP': 1.1}), ('apple', {'USD': 2, 'EUR': 1.8, 'GBP': 1.6})]

Usar itemgetter(1, "USD") como a chave de ordenação é mais eficiente do que usar uma função lambda que extrairia o valor a cada comparação.

Medindo o Desempenho ao Usar itemgetter()

Se você está preocupado com o desempenho ao usar a função itemgetter() para ordenar um dicionário, pode usar o módulo timeit para medir o tempo de execução e comparar com uma função lambda.

Vamos supor que você tenha o seguinte dicionário de produtos com 100.000 itens:

import random
produtos = {str(i): random.randint(1, 1000) for i in range(100000)}

Se você deseja ordenar esse dicionário pelos valores em ordem ascendente usando itemgetter(), pode fazer o seguinte:

from operator import itemgetter
import timeit
tempo_itemgetter = timeit.timeit("sorted(produtos.items(), key=itemgetter(1))", globals=globals(), number=10)
print(f"Tempo itemgetter: {tempo_itemgetter}")

Isso medirá o tempo de execução do código 10 vezes e imprimirá o tempo médio. Você pode comparar esse tempo com o tempo de execução usando uma função lambda:

tempo_lambda = timeit.timeit("sorted(produtos.items(), key=lambda x: x[1])", globals=globals(), number=10)
print(f"Tempo lambda: {tempo_lambda}")

Com base na medição, você pode determinar qual método oferece melhor desempenho para o seu caso de uso específico.

Decidindo se Deseja Usar um Dicionário Ordenado

Embora seja possível ordenar um dicionário em Python, na prática, ordenar dicionários não é uma prática comum. Os dicionários são projetados para fornecer acesso rápido aos valores com base em suas chaves, e não para serem ordenados.

Se você precisa de uma estrutura de dados que mantenha uma ordem específica, pode considerar outras alternativas, como a classe OrderedDict do módulo collections.

A decisão de usar um dicionário ordenado deve levar em consideração as necessidades específicas do seu programa, como a frequência de inserção, exclusão e acesso aos elementos.

Comparando o Desempenho de Diferentes Estruturas de Dados

Quando se trata de desempenho, é sempre importante comparar diferentes estruturas de dados para ver qual se adequa melhor às suas necessidades.

Se você está preocupado com o desempenho ao usar dicionários ordenados em Python, pode comparar o desempenho com outras estruturas de dados, como listas ou conjuntos.

Por exemplo, vamos supor que você tenha o seguinte dicionário de produtos com 100.000 itens:

import random
produtos = {str(i): random.randint(1, 1000) for i in range(100000)}

Se você deseja ordenar esse dicionário pelos valores em ordem ascendente usando sorted(), pode converter o dicionário em uma lista e usar a função sorted() diretamente:

lista_produtos = list(produtos.items())
tempo_lista = timeit.timeit("sorted(lista_produtos, key=lambda x: x[1])", globals=globals(), number=10)
print(f"Tempo lista: {tempo_lista}")

Isso medirá o tempo de execução do código 10 vezes e imprimirá o tempo médio. Você também pode comparar o desempenho com um conjunto, que é uma estrutura de dados que não mantém uma ordem específica:

conjunto_produtos = set(produtos.items())
tempo_conjunto = timeit.timeit("sorted(conjunto_produtos, key=lambda x: x[1])", globals=globals(), number=10)
print(f"Tempo conjunto: {tempo_conjunto}")

Essas comparações podem ajudá-lo a tomar uma decisão informada sobre qual estrutura de dados usar com base no desempenho específico que você precisa.

Comparando o Desempenho da Ordenação

Outro aspecto importante a ser considerado é o desempenho real da ordenação. Dependendo do tamanho do dicionário e da quantidade de elementos a serem ordenados, a função sorted() pode levar algum tempo para concluir a ordenação.

Você pode medir o tempo de execução da ordenação usando o módulo timeit e comparar o desempenho em diferentes cenários.

Você também pode considerar o uso de algoritmos de ordenação específicos, como o algoritmo de classificação rápida (quicksort), para obter um desempenho aprimorado.

Conclusão

Ordenar um dicionário em Python pode ser feito usando a função sorted() em conjunto com os parâmetros key e reverse, além de funções lambda para especificar a chave de ordenação. Também é possível utilizar as compreensões de dicionário ou o construtor dict() para reconstruir o dicionário a partir de uma lista de pares de chave-valor ordenados.

Ao trabalhar com dicionários ordenados, é importante considerar questões estratégicas e de desempenho, como o uso de funções getter especiais para aumentar a legibilidade e o desempenho do código, medir o desempenho ao usar essas funções, decidir se um dicionário ordenado é realmente necessário para o seu caso de uso e comparar o desempenho de diferentes estruturas de dados e algoritmos de ordenação.

Embora seja possível ordenar dicionários em Python, é importante lembrar que os dicionários foram projetados para fornecer acesso rápido aos valores com base em suas chaves, e não para serem ordenados. Portanto, a decisão de usar dicionários ordenados deve ser baseada nas necessidades específicas do seu programa.