Comparando Métodos de Ordenação em Python: `sort()` vs `sorted()`

Em Python, tanto list.sort() quanto a função embutida sorted() são utilizados para ordenar elementos. No entanto, suas naturezas e comportamentos fundamentais diferem significativamente. A distinção crucial reside no fato de que list.sort() é um método que opera diretamente em uma lista, modificando-a no lugar, enquanto sorted() é uma função que retorna uma nova lista ordenada, deixando a coleção original intocada.

A tabela a seguir detalha as principais diferenças:

Característica lista.sort() sorted(iteravel)
Tipo Método intrínseco de objetos do tipo list Função embutida do Python
Retorno None (modifica o objeto original diretamente) Retorna um novo objeto list ordenado
Objeto Original É modificado Não é modificado
Aplicabilidade Exclusivamente para objetos list Qualquer objeto iterável (tuplas, strings, dicionários, conjuntos, etc.)
Formato de Uso minha_lista.sort() sorted(meu_iteravel)

Exemplos de Utilização

1. Ordenação de Listas

Observe como a lista original é afetada em cada caso:


numeros_originais = [5, 2, 8, 1, 3]

# Usando list.sort()
lista_para_modificar = list(numeros_originais) # Criando uma cópia para demonstração
lista_para_modificar.sort()
print(f"Após sort(): {lista_para_modificar}") # Saída: [1, 2, 3, 5, 8] (lista modificada)
print(f"Lista original: {numeros_originais}") # Saída: [5, 2, 8, 1, 3] (a cópia foi modificada, a original não foi passada)

# Usando sorted()
lista_ordenada_nova = sorted(numeros_originais)
print(f"Após sorted(): {lista_ordenada_nova}") # Saída: [1, 2, 3, 5, 8] (nova lista)
print(f"Lista original: {numeros_originais}") # Saída: [5, 2, 8, 1, 3] (lista original inalterada)
   

2. Ordenação de Outros Iteráveis

A função sorted() é versátil e pode ser aplicada a diversos tipos de coleções iteráveis, que não possuem o método .sort():


# Tupla
minha_tupla = (9, 3, 6, 1)
resultado_tupla = sorted(minha_tupla)
print(f"Tupla ordenada (resulta em lista): {resultado_tupla}") # Saída: [1, 3, 6, 9]

# String (ordena caracteres individualmente)
minha_string = "algoritmo"
resultado_string = sorted(minha_string)
print(f"String ordenada (resulta em lista de caracteres): {resultado_string}") # Saída: ['a', 'g', 'i', 'l', 'm', 'o', 'r', 't']

# Dicionário (ordena as chaves por padrão)
meu_dicionario = {'banana': 2, 'maçã': 1, 'abacate': 3}
chaves_ordenadas = sorted(meu_dicionario)
print(f"Chaves do dicionário ordenadas: {chaves_ordenadas}") # Saída: ['abacate', 'banana', 'maçã']
   

3. Parâmetros key e reverse

Ambos os mecanismos de ordenação, list.sort() e sorted(), oferecem os parâmetros opcionais key e reverse para personalizar o comportamento da ordenação.

  • key: Aceita uma função de um argumento que será aplicada a cada elemento antes da comparação. O valor retornado por essa função será usado como a "chave" para a ordenação.

    
    nomes_frutas = ["uva", "banana", "kiwi", "abacaxi"]
    nomes_frutas.sort(key=len) # Ordena pelo comprimento das strings
    print(f"Nomes de frutas por comprimento: {nomes_frutas}") # Saída: ['uva', 'kiwi', 'banana', 'abacaxi']
    
    dados_numericos = [3.14, -1.5, 0.75, -2.0]
    ordenado_por_modulo = sorted(dados_numericos, key=abs) # Ordena pelo valor absoluto
    print(f"Valores por módulo: {ordenado_por_modulo}") # Saída: [0.75, -1.5, -2.0, 3.14]
    
    
  • reverse: Um valor booleano (True ou False). Se True, a lista é ordenada em ordem decrescente (do maior para o menor). O padrão é False (ordem crescente).

    
    valores = [10, 30, 20, 50, 40]
    
    # Ordenação decrescente com sorted()
    valores_decrescentes = sorted(valores, reverse=True)
    print(f"Valores em ordem decrescente: {valores_decrescentes}") # Saída: [50, 40, 30, 20, 10]
    
    # Ordenação decrescente com sort()
    minha_lista = [10, 30, 20, 50, 40]
    minha_lista.sort(reverse=True)
    print(f"Lista modificada em ordem decrescente: {minha_lista}") # Saída: [50, 40, 30, 20, 10]
    
    

Diferença na Assinatura dos Parâmetros

Apesar de ambos aceitarem key e reverse, a forma como os parâmetros são passados é diferente devido às suas naturezas distintas:

  • lista.sort(key=None, reverse=False): Como é um método de lista, ele já "sabe" qual objeto deve ordenar (a própria lista que o chamou). Portanto, ele aceita apenas parâmetros que controlam o processo de ordenação.
  • sorted(iteravel, key=None, reverse=False): Sendo uma função autônoma, ela precisa explicitamente do primeiro argumento (iteravel) para saber qual coleção deve ser ordenada. Em seguida, os parâmetros de controle de ordenação são fornecidos.

Utilizando lambda com sort() e sorted()

Funções lambda são frequentemente empregadas como valor para o parâmetro key, permitindo a criação de funções de ordenação concisas e anônimas diretamente no local. Elas servem para extrair um "critério" ou "valor-chave" de cada item, que será usado para a comparação.

Sintaxe Básica


# Para o método .sort()
minha_lista.sort(key=lambda item: expressao_para_extrair_chave, reverse=False)

# Para a função sorted()
nova_lista_ordenada = sorted(iteravel, key=lambda item: expressao_para_extrair_chave, reverse=False)
   
  • item: Representa cada elemento do iterável sendo ordenado.
  • expressao_para_extrair_chave: Define qual atributo, cálculo ou transformação do item será usado para a comparação.

Exemplos em Estruturas de Dados Comuns

1. Ordenando Tuplas pelo Segundo Elemento

pontuacoes = [('Ana', 90), ('Carlos', 85), ('Beatriz', 95)]

# Ordenar por pontuação (segundo elemento da tupla) em ordem crescente
pontuacoes.sort(key=lambda dados: dados[1])
print(f"Ordenado por pontuação (crescente): {pontuacoes}")
# Saída: [('Carlos', 85), ('Ana', 90), ('Beatriz', 95)]

# Ordenar por pontuação em ordem decrescente
pontuacoes.sort(key=lambda dados: dados[1], reverse=True)
print(f"Ordenado por pontuação (decrescente): {pontuacoes}")
# Saída: [('Beatriz', 95), ('Ana', 90), ('Carlos', 85)]
   
2. Ordenando Dicionários por Valor de Chave Específica

usuarios = [
   {'nome': 'Pedro', 'idade': 28},
   {'nome': 'Maria', 'idade': 32},
   {'nome': 'João', 'idade': 25}
]

# Ordenar por idade usando sorted()
usuarios_ordenados = sorted(usuarios, key=lambda pessoa: pessoa['idade'])
print(f"Usuários ordenados por idade: {usuarios_ordenados}")
# Saída: [{'nome': 'João', 'idade': 25}, {'nome': 'Pedro', 'idade': 28}, {'nome': 'Maria', 'idade': 32}]
   

Ordenação de Estruturas Complexas

1. Ordenação Multi-Critério (Primeiro Critério, Depois Segundo)

É possível ordenar com base em múltiplos critérios, retornando uma tupla na função key. A ordenação será feita sequencialmente pelos elementos da tupla.


alunos = [
   ('Lucas', 75, 17),
   ('Sofia', 90, 16),
   ('Gabriel', 75, 18),
   ('Isabela', 90, 15)
]

# Ordenar: primeiro pela nota (decrescente), depois pela idade (crescente)
alunos.sort(key=lambda aluno: (-aluno[1], aluno[2])) # -aluno[1] inverte a ordem da nota
print(f"Alunos ordenados por nota e idade: {alunos}")
# Saída: [('Isabela', 90, 15), ('Sofia', 90, 16), ('Lucas', 75, 17), ('Gabriel', 75, 18)]
   
2. Ordenando Strings por Característica Específica

linguagens = ['java', 'python', 'csharp', 'go', 'javascript']

# Ordenar por comprimento da string
linguagens.sort(key=lambda s: len(s))
print(f"Linguagens por comprimento: {linguagens}")
# Saída: ['go', 'java', 'python', 'csharp', 'javascript']

# Ordenar pelo último caractere da string
linguagens.sort(key=lambda s: s[-1])
print(f"Linguagens pelo último caractere: {linguagens}")
# Saída: ['java', 'csharp', 'go', 'python', 'javascript']
   
Explicação sobre Acesso aos Elementos (x[1] vs x[-1])

A forma como você acessa os elementos dentro do lambda depende do tipo de item na lista:

  • Se a lista contém tuplas (e você quer acessar um elemento da tupla), use x[indice]. Ex: lista_de_tuplas = [(1, 'um'), (2, 'dois')]. Para ordenar pelo segundo elemento da tupla, key=lambda x: x[1].

  • Se a lista contém strings (e você quer acessar um caractere da string), use x[indice]. Ex: lista_de_strings = ['casa', 'bola']. Para ordenar pelo último caractere, key=lambda x: x[-1].

  • Se a lista contém dicionários (e você quer acessar um valor por chave), use x['chave']. Ex: lista_de_dicts = [{'id': 1}, {'id': 2}]. Para ordenar por 'id', key=lambda x: x['id'].

  • Se a lista contém instâncias de objetos (e você quer acessar um atributo), use x.atributo. Ex: ```python

    class Produto: def init(self, nome, preco): self.nome = nome self.preco = preco

    produtos = [Produto('Caneta', 5.0), Produto('Lápis', 2.5)] produtos.sort(key=lambda prod: prod.preco) # Acesso ao atributo 'preco'

    
    
3. Ordenando Logs por Parte do Texto

registros_logs = [
   '2023-11-20 14:05:10 - INFO: Aplicação iniciada',
   '2023-11-20 10:00:00 - ERROR: Falha na conexão',
   '2023-11-20 12:30:15 - WARNING: Disco cheio'
]

# Ordenar por parte da hora (segundo elemento após split por espaço)
registros_logs.sort(key=lambda log: log.split()[1])
print(f"Logs ordenados por hora: {registros_logs}")
# Saída (ordenado por 10:00:00, 12:30:15, 14:05:10):
# ['2023-11-20 10:00:00 - ERROR: Falha na conexão',
#  '2023-11-20 12:30:15 - WARNING: Disco cheio',
#  '2023-11-20 14:05:10 - INFO: Aplicação iniciada']
   

Erros Comuns e Recomendações

1. lambda Retornando Booleano para Ordenação Numérica/Complexa

Usar um lambda que retorna True ou False para o parâmetro key não produzirá a ordenação esperada, pois os elementos serão agrupados e ordenados apenas com base nesses dois valores booleanos.


# Uso incorreto:
palavras = ['maçã', 'banana', 'a', 'cereja']
# palavras.sort(key=lambda item: len(item) > 4) # Isso ordenaria por True/False, não pelo comprimento exato
# Resultado imprevisível ou não intuitivo: ['a', 'maçã', 'banana', 'cereja'] ou similar, dependendo da ordem relativa de True/False

# Correto: Retornar o valor que realmente servirá de critério de comparação
palavras.sort(key=lambda item: len(item))
print(f"Palavras ordenadas por comprimento (correto): {palavras}")
# Saída: ['a', 'maçã', 'banana', 'cereja']
   

2. Esquecer o Parâmetro key=

O lambda deve ser explicitamente atribuído ao parâmetro key. Caso contrário, Python tentará interpretar a função lambda como o primeiro argumento posicional (o iterável para sorted() ou um argumento inválido para sort()), resultando em um erro.


valores_abs = [-3, 1, -2, 4]

# Erro: A função lambda não é o iterável, nem um argumento posicional válido para sort()
# valores_abs.sort(lambda x: abs(x)) # Geraria TypeError

# Correto: Atribuir a função lambda ao parâmetro key
valores_abs.sort(key=lambda x: abs(x))
print(f"Valores ordenados por valor absoluto: {valores_abs}")
# Saída: [1, -2, -3, 4]
   

Tags: Python sorting list.sort sorted() Lambda

Publicado em 10-11 13:56