Pular para o conteúdo

Como ordenar dicionários em Python por valor

[

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

Você tem um dicionário, mas gostaria de ordenar os pares chave-valor. Talvez você já 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 visões de dicionário para iterar sobre eles
  • Como os dicionários são transformados 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 compreensões de dicionário e o construtor dict() para reconstruir seus dicionários
  • Alternativas de estruturas de dados para seus dados chave-valor

Ao longo do caminho, você também usará o módulo timeit para cronometrar 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 particularmente comum.

Para aproveitar ao máximo este tutorial, você deve conhecer os conceitos de dicionários, listas, tuplas e funções. Com esse conhecimento, você será capaz de ordenar dicionários até o final deste tutorial. Alguma exposição a funções de ordem superior, como funções lambda, também será útil, mas não é um requisito.

Download Grátis: [Clique aqui para baixar o

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

Descobrindo a Ordem dos Dicionários em Python

Antes do Python 3.6, os dicionários eram inherentemente não ordenados. Um dicionário Python é uma implementação da tabela de hash, que tradicionalmente é uma estrutura de dados não ordenada.

Como efeito colateral da implementação do dicionário compacto em Python 3.6, os dicionários passaram a preservar a ordem de inserção. A partir da versão 3.7, essa ordem de inserção foi garantida.

Se você desejava manter um dicionário ordenado como uma estrutura de dados antes do Python 3.6, tinha que usar a classe OrderedDict do módulo collections. No entanto, a partir do Python 3.6, o dicionário embutido já preserva a ordem e você não precisa mais do OrderedDict para esse fim.

Vamos começar com um exemplo simples de um dicionário:

frutas = {'banana': 3, 'maçã': 1, 'laranja': 2, 'uva': 4}

Se você imprimir o dicionário, verá algo como:

{'banana': 3, 'maçã': 1, 'laranja': 2, 'uva': 4}

Observe que a ordem dos pares chave-valor é a mesma em que você inseriu o dicionário. Agora, vamos explorar diferentes formas de ordenar esse dicionário.

Usando a Função sorted()

Uma maneira simples de ordenar um dicionário é usar a função sorted(). Essa função recebe um iterável como argumento e retorna uma nova lista contendo os elementos em ordem.

Vamos ordenar o dicionário de frutas em ordem crescente com base nos valores:

frutas_ordenadas = sorted(frutas.items(), key=lambda x: x[1])

A função items() retorna uma visão do dicionário como uma sequência de tuplas chave-valor. Usamos o argumento key para especificar que queremos ordenar com base no segundo elemento da tupla (os valores).

Agora, se imprimirmos frutas_ordenadas, teremos:

[('maçã', 1), ('laranja', 2), ('banana', 3), ('uva', 4)]

A lista está ordenada com base nos valores do dicionário. Observe que a ordem das chaves é mantida.

Obtendo Chaves, Valores ou Ambos de um Dicionário

Em alguns casos, você pode precisar apenas das chaves ou apenas dos valores ao ordenar um dicionário. Você pode usar as seguintes visões de dicionário para isso:

  • dict.keys(): Retorna uma visão das chaves do dicionário
  • dict.values(): Retorna uma visão dos valores do dicionário
  • dict.items(): Retorna uma visão das tuplas chave-valor do dicionário

Por exemplo, se quisermos ordenar apenas as chaves do dicionário de frutas, podemos fazer o seguinte:

chaves_ordenadas = sorted(frutas.keys())

Isso nos dará a seguinte lista:

['banana', 'laranja', 'maçã', 'uva']

Da mesma forma, se quisermos ordenar apenas os valores, podemos fazer o seguinte:

valores_ordenados = sorted(frutas.values())

Isso nos dará a seguinte lista:

[1, 2, 3, 4]

Entendendo Como o Python Ordena Tuplas

Ao usar a função sorted() para ordenar um dicionário, você pode especificar um parâmetro key para definir uma função de ordenação personalizada. Essa função de ordenação deve receber cada elemento do iterável e retornar um valor que será usado para comparar os elementos.

Quando você fornece um lambda ou uma função personalizada como chave de ordenação, o Python usará esse valor retornado para classificar os elementos. No caso de um dicionário, cada elemento é uma tupla chave-valor.

Você pode especificar qual elemento da tupla deve ser usado para ordenar os elementos, com base em sua posição. Por exemplo, se a função de ordenação for lambda x: x[1], o Python usará o segundo elemento da tupla para classificar os elementos.

Se você deseja ordenar por mais de um elemento da tupla, é possível fornecer uma função de ordenação personalizada que retorna uma tupla contendo esses elementos. Por exemplo, lambda x: (x[1], x[0]) ordenará primeiro com base no segundo elemento e, em seguida, com base no primeiro elemento da tupla.

Vamos ver um exemplo em que queremos ordenar um dicionário com base nas chaves:

livros = {'Python Crash Course': 20, 'Fluent Python': 15, 'Clean Code': 10}
livros_ordenados = sorted(livros.items(), key=lambda x: x[0])

Aqui, estamos ordenando o dicionário livros com base nas chaves (primeiro elemento da tupla). O resultado será:

[('Clean Code', 10), ('Fluent Python', 15), ('Python Crash Course', 20)]

Observe que os elementos estão ordenados alfabeticamente de acordo com as chaves.

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

O Python permite usar uma função personalizada como chave de ordenação. Você pode criar uma função lambda para esse propósito. A função lambda deve receber um parâmetro (que será um elemento do iterável) e retornar um valor com base no qual os elementos serão ordenados.

Por exemplo, se quisermos ordenar o dicionário de frutas com base no tamanho das palavras-chave em ordem decrescente, podemos fazer o seguinte:

frutas_ordenadas = sorted(frutas.items(), key=lambda x: len(x[0]), reverse=True)

A função lambda lambda x: len(x[0]) retorna o tamanho da palavra-chave (primeiro elemento da tupla) de cada par chave-valor. E definimos reverse=True para obter a ordem decrescente. O resultado será:

[('laranja', 2), ('banana', 3), ('uva', 4), ('maçã', 1)]

Observe que os elementos estão ordenados em ordem decrescente com base no tamanho das palavras-chave.

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

Imagine que temos um dicionário de estudantes, onde cada chave é o nome de um estudante e cada valor é um dicionário contendo suas notas em diferentes disciplinas. Queremos ordenar esse dicionário com base na média das notas de cada estudante.

Primeiro, precisamos de um dicionário de exemplo:

estudantes = {
'João': {'Matemática': 9, 'Português': 8, 'História': 10},
'Maria': {'Matemática': 7, 'Português': 9, 'História': 6},
'Pedro': {'Matemática': 6, 'Português': 7, 'História': 8}
}

Agora podemos usar uma função lambda como chave de ordenação para obter a média das notas de cada estudante:

estudantes_ordenados = sorted(estudantes.items(), key=lambda x: sum(x[1].values()) / len(x[1]), reverse=True)

A função lambda lambda x: sum(x[1].values()) / len(x[1]) calcula a média das notas (valores do dicionário) do estudante (segundo elemento da tupla) e retorna esse valor. Definimos reverse=True para obter a ordem decrescente. O resultado será:

[('João', {'Matemática': 9, 'Português': 8, 'História': 10}),
('Pedro', {'Matemática': 6, 'Português': 7, 'História': 8}),
('Maria', {'Matemática': 7, 'Português': 9, 'História': 6})]

Observe que os elementos estão ordenados em ordem decrescente com base na média das notas.

Convertendo de Volta para um Dicionário

Se você deseja retornar um dicionário ordenado em vez de uma lista de tuplas, pode usar o construtor dict().

Por exemplo, se quisermos retornar o dicionário de frutas ordenado pelos valores em ordem crescente, podemos fazer o seguinte:

frutas_ordenadas_dict = dict(sorted(frutas.items(), key=lambda x: x[1]))

Obteremos o seguinte dicionário:

{'maçã': 1, 'laranja': 2, 'banana': 3, 'uva': 4}

O dicionário agora está ordenado com base nos valores.

Considerando Aspectos Estratégicos e de Desempenho

Quando você está ordenando um dicionário ou qualquer outro tipo de estrutura de dados, é importante considerar os aspectos estratégicos e de desempenho envolvidos.

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

Ao usar a função sorted() em um dicionário grande, pode haver uma diminuição no desempenho, pois a função sorted() precisa extrair as chaves e os valores do dicionário antes de ordená-los.

Uma maneira de melhorar o desempenho é usar as funções getter especiais operator.itemgetter() ou attrgetter() em vez de uma função lambda como chave de ordenação. Essas funções ajudam a evitar a extração explícita das chaves e valores antes da ordenação.

Por exemplo, se quisermos ordenar o dicionário de frutas com base nos valores usando operator.itemgetter():

from operator import itemgetter
frutas_ordenadas = sorted(frutas.items(), key=itemgetter(1))

Essa abordagem pode melhorar a velocidade de execução em comparação com a função lambda.

Medindo o Desempenho ao Usar itemgetter()

Para ter uma ideia do desempenho ao usar itemgetter(), você pode usar o módulo timeit para cronometrar o tempo de execução do seu código.

Por exemplo, você pode usar o seguinte código para comparar o desempenho ao usar itemgetter() e uma função lambda como chave de ordenação:

import timeit
from operator import itemgetter
frutas = {'banana': 3, 'maçã': 1, 'laranja': 2, 'uva': 4}
def ordenar_com_itemgetter():
sorted(frutas.items(), key=itemgetter(1))
def ordenar_com_lambda():
sorted(frutas.items(), key=lambda x: x[1])
tempo_itemgetter = timeit.timeit(ordenar_com_itemgetter, number=1000000)
tempo_lambda = timeit.timeit(ordenar_com_lambda, number=1000000)
print(f"Tempo usando itemgetter(): {tempo_itemgetter}")
print(f"Tempo usando lambda: {tempo_lambda}")

Você pode ajustar o número de vezes que cada função é executada para obter um resultado mais preciso.

Avaliando se Você Deseja Usar um Dicionário Ordenado

Criar um dicionário ordenado envolve custos adicionais de desempenho e pode não ser a melhor opção para todas as situações. Antes de decidir usar um dicionário ordenado, avalie se outros tipos de estruturas de dados (como listas ou conjuntos) podem atender melhor aos seus requisitos.

Um dicionário ordenado é útil quando você precisa iterar sobre os elementos em uma ordem específica com base em chaves ou valores. Se a ordem dos elementos não for importante, um dicionário comum pode ser mais eficiente.

Comparando o Desempenho de Diferentes Estruturas de Dados

Além de comparar o desempenho da ordenação em si, também é importante considerar o desempenho das diferentes estruturas de dados em termos de acesso e modificação dos elementos.

Por exemplo, uma lista é eficiente para acessar elementos pelo índice, mas menos eficiente para verificar se um elemento está presente. Um conjunto, por outro lado, é eficiente para verificar a existência de elementos, mas não preserva a ordem de inserção.

Considere suas necessidades específicas ao escolher a estrutura de dados correta.

Comparando o Desempenho da Ordenação

Ao lidar com grandes quantidades de dados e necessidades de desempenho altas, é importante considerar o desempenho da ordenação em si.

Você pode usar o módulo timeit para medir o tempo de execução de diferentes métodos de ordenação e escolher o melhor para suas necessidades.

Por exemplo, você pode usar o seguinte código para comparar o desempenho de diferentes formas de ordenação:

import timeit
from operator import itemgetter
frutas = {'banana': 3, 'maçã': 1, 'laranja': 2, 'uva': 4}
def ordenar_com_sorted():
sorted(frutas.items(), key=itemgetter(1))
def ordenar_com_lista():
sorted([(k, v) for k, v in frutas.items()], key=itemgetter(1))
def ordenar_com_dict():
dict(sorted(frutas.items(), key=itemgetter(1)))
tempo_sorted = timeit.timeit(ordenar_com_sorted, number=100000)
tempo_lista = timeit.timeit(ordenar_com_lista, number=100000)
tempo_dict = timeit.timeit(ordenar_com_dict, number=100000)
print(f"Tempo usando sorted(): {tempo_sorted}")
print(f"Tempo usando lista: {tempo_lista}")
print(f"Tempo usando dicionário: {tempo_dict}")

Você pode ajustar o número de vezes que cada função é executada para obter um resultado mais preciso.

Comparando o Desempenho das Pesquisas

Além de considerar o desempenho da ordenação, também é importante considerar o desempenho das pesquisas em diferentes estruturas de dados.

Por exemplo, um dicionário permite pesquisas rápidas por chave, mas não permite pesquisas por valor. Uma lista pode ser pesquisada por valor, mas o tempo de execução será proporcional ao tamanho da lista.

Considere suas necessidades específicas ao escolher a estrutura de dados correta.

Conclusão

Neste tutorial, você aprendeu várias maneiras de ordenar dicionários em Python. A função sorted() é útil para ordenar um dicionário com base nas chaves, valores ou ambos. Você também pode especificar uma chave de ordenação personalizada usando uma função lambda. Além disso, considerou aspectos estratégicos e de desempenho ao trabalhar com dicionários e outras estruturas de dados.

Lembre-se de considerar suas necessidades específicas e avaliar o desempenho das diferentes formas de ordenação e estruturas de dados ao escolher a melhor solução para seu caso.

Agora você está pronto para aplicar esses conceitos em seus próprios projetos Python. Experimente e aproveite a flexibilidade e a eficiência que as ordenações de dicionários podem oferecer!