Ordenação de uma lista

É comum termos uma lista toda bagunçada e querermos ordenar os elementos contidos nela. Para ordenar uma lista de valores, basta chamar o método sort da lista.

Vamos ver como isso funciona na prática. Primeiramente, vamos criar uma lista com 10 elementos e depois bagunçá-la usando a função shuffle, do módulo random.

>>> lista = range(10)
>>> lista
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> import random
>>> random.shuffle(lista)
>>> lista
[2, 5, 4, 1, 3, 6, 9, 7, 0, 8]

Tudo que precisamos fazer para ordenar uma lista desordenada é:

>>> lista.sort()
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Barbada! Também podemos ordená-la de forma descendente:

>>> lista.sort(reverse=True)
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

A ordenação de inteiros ou de valores de tipos de dados simples é bem trivial. Porém, se quisermos ordenar uma lista que contém instâncias de uma classe, precisaremos utilizar o parâmetro key do sort.

O parâmetro key

O parâmetro key do método sort espera uma função que será chamada uma vez para cada um dos elementos da lista e o retorno dessa função será utilizado na comparação com os outros elementos da lista.

Considere que temos uma classe Aluno, conforme o código abaixo:

class Aluno:
	def __init__(self, nome, matricula):
		self.nome = nome
		self.matricula = matricula

	def __str__(self):
		return "%s - %s" % (str(self.nome), str(self.matricula))

Dada uma lista chamada alunos contendo n objetos do tipo Aluno, como ordená-la? Se chamarmos alunos.sort(), sem especificar como queremos que ela seja ordenada, o sort irá ordená-la através de comparações dos endereços de memória dos objetos contidos na lista alunos. Se quisermos que a ordenação se dê por algum dos atributos da classe, devemos especificar isso através do parâmetro key.

Vamos primeiramente criar uma lista com objetos de conteúdo aleatório:

>>> alunos = [Aluno("".join(random.sample(string.ascii_letters, 5)), random.randint(0, 100)) for i in range(10)]
>>> for aluno in alunos:
		print aluno
zfbnu - 12
sxbIX - 77
vJCIN - 33
aBjZA - 70
fNLeS - 19

Bonitos os nomes deles, né? Agora, vamos ordená-los:

>>> alunos.sort(key=lambda a: a.nome)
>>> for aluno in alunos:
        print aluno
aBjZA - 70
fNLeS - 19
sxbIX - 77
vJCIN - 33
zfbnu - 12

O que fizemos foi especificar como queremos que os elementos sejam comparados.  Para isso, criamos uma função anônima que recebe como parâmetro um objeto e retorna o elemento a ser usado na comparação (o atributo nome). O mesmo poderia ser feito com uma função nomeada, como:

>>> def key_func(aluno):
...     return aluno.nome
>>> alunos.sort(key=key_func)
>>> for aluno in alunos:
...     print aluno

Porém, ter que criar uma função (anônima ou não) somente para indicar qual atributo deverá ser usado na ordenação é um pouco inconveniente. Por isso, vamos utilizar o outro mecanismo que permite que façamos a mesma coisa. Ao invés de criarmos uma função que recebe um objeto e retorna o atributo nome daquele objeto, vamos usar a função attrgetter do módulo operator, que retorna o valor do atributo solicitado no objeto em questão.

>>> from operator import attrgetter
>>> alunos.sort(key=attrgetter("nome"))

A função attrgetter irá retornar uma outra função que quando chamada sobre cada objeto x contido na lista alunos, irá retornar x.nome.

Ou seja, para cada objeto Aluno contido na lista, será chamado o método attrgetter, solicitando o atributo nome.

Ordenando uma lista de listas

Já vi muito código que utiliza lista ou tupla como mecanismo para agrupar dados. Ao invés de criar uma classe ou uma namedtuple, o cara vai lá e empacota os dados que deseja em uma tupla. Por exemplo, ao invés de criar uma classe Aluno, poderíamos ter empacotado os dados referentes a cada aluno em uma tupla. Veja:

>>> alunos = [("Jose", 12345), ("Maria", 28374), ("Joao", 11119), ("Joana", 12346)]

Para ordenar uma lista desse tipo, podemos continuar usando o método sort e o parâmetro key, e agora vamos especificar qual elemento das tuplas que compõem a lista será utilizado na comparação para definir qual elemento precede qual na ordem. No exemplo abaixo, estamos ordenando os alunos pelo número da matrícula.

>>> alunos.sort(key=lambda x: x[1])
>>> print alunos
[('Joao', 11119), ('Jose', 12345), ('Joana', 12346), ('Maria', 28374)]

A função anônima poderia ser evitada novamente usando a função itemgetter:

>>> from operator import itemgetter
>>> alunos.sort(key=itemgetter(1))

O itemgetter é bem parecido com o attrgetter, com a diferença de que passamos para ele o índice do elemento que queremos que seja usado na comparação que será feita ao ordenar a lista.

Mas fique atento, o método sort está presente somente nas listas. Para ordenar outros objetos iteráveis, dê uma olhada na função builtin sorted.

8 comentários sobre “Ordenação de uma lista

  1. Pingback: #4 – Python rulez | Aprendendo Python
  2. Pingback: Como funcionam as listas de Python? | Python Help
  3. Pingback: Como funcionam as listas de Python? - Peguei do
  4. Pingback: Ordenação de uma lista - Peguei do

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s