Estruturas de Dados

Listas

Em Python, listas de objetos são representadas pelo tipo list. Esse tipo de dados é basicamente uma sequência de elementos, que podem ou não ser do mesmo tipo.

A sintaxe para a criação de listas em Python é [...]. Veja os exemplos abaixo para mais detalhes:

# Cria uma lista sem nenhum elemento. 
lista_vazia = [] # A expressão lista_vazia = list() possui o mesmo efeito.
print("Lista vazia: ", lista_vazia)
print("Tipo de uma lista: ", type(lista_vazia))

lista_inteiros = [10, 20, 30, 40]
print("Lista de inteiros: ", lista_inteiros)

lista_tipos_diferentes = ["George", "Orwell", 1984]
print("Lista de elementos com tipos diferentes: ", lista_tipos_diferentes)

Lista vazia:  []
Tipo de uma lista:  <class 'list'>
Lista de inteiros:  [10, 20, 30, 40]
Lista de elementos com tipos diferentes:  ['George', 'Orwell', 1984]

A sintaxe para se operar com listas é similar à sintaxe de strings. Um exemplo de tal similaridade é o uso de slicing:

print(lista_inteiros)

print(lista_inteiros[1:3]) # Retorna os índices 1 e 2 da lista.

print(lista_inteiros[::2]) # Imprime a lista, saltando de dois em dois elementos.
[10, 20, 30, 40]
[20, 30]
[10, 30]

Python permite listas aninhadas. Este recurso é útil quando desejamos criar listas de várias dimensões (ou matrizes):

lista_aninhada = [1, [2, [3, [4]]], 5]
print("Lista aninhada: ", lista_aninhada)

matriz = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print("Matriz 3x3: ", matriz)

# A sintaxe abaixo será explicada posteriormente.
print("Matriz impressa de outra forma:")
for lista in matriz:
    for elemento in lista:
        print(elemento, end=' ')
    print()
Lista aninhada:  [1, [2, [3, [4]]], 5]
Matriz 3x3:  [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Matriz impressa de outra forma:
1 2 3 
4 5 6 
7 8 9 

Linguagens de programação como C, C++, e Java usam índices para iterar sobre listas de elementos. Em Python, normalmente percorremos listas de elementos sem que existam índices associados a eles. Entretanto, em algumas situações desejamos percorrer uma lista (de números, por exemplo) em determinada ordem. Python nos permite fazer por meio de intervalos, usando a função range(), como mostrado abaixo:

# Sintaxe da função range().

inicio = 0
fim = 100
passo = 10

print("Convertendo um intervalo em uma lista: ", list(range(inicio, fim, passo)))
Convertendo um intervalo em uma lista:  [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]

Perceba que o elemento final do intervalo (no caso acima, o 100) não é retornado pela função range(). O exemplo abaixo mostra isso melhor. Além disso, se não fornecermos o passo, a função irá usar o valor padrão 1.

# Funcionamento da função range. Note que o 10 não é incluído no resultado.
print(list(range(0, 10)))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Como mencionado anteriomente, listas e strings possuem um funcionamento bem parecido em Python. Em muitas situações, entretanto, é preciso convertermos um tipo no outro. Python oferece meios de se fazer isso, como mostrado abaixo.

# Converte uma string em uma lista.
# O mesmo resultado é obtido se usarmos s = "Ordem e Progresso".split()
s = list("Ordem e Progresso")
print(s)

# Converte uma lista em uma string.
l = ['O', 'r', 'd', 'e', 'm', ' ', 'e', ' ', 'P', 'r', 'o', 'g', 'r', 'e', 's', 's', 'o']
print(''.join(l))
['O', 'r', 'd', 'e', 'm', ' ', 'e', ' ', 'P', 'r', 'o', 'g', 'r', 'e', 's', 's', 'o']
Ordem e Progresso

Em linguagens como C, uma string é basicamente uma lista (um arranjo, para ser mais exato) de caracteres. Em Python isso é diferente: uma lista de caracteres é diferente de uma string.

A principal diferença entre strings e listas em Python é que strings são imutáveis, enquanto listas são mutáveis. Quando tentamos modificar uma strings estamos, na verdade, criando uma nova string com as modificações feitas. Em se tratando de listas, as modificações são feitas sem que se crie uma nova cópia da lista.

Existem também algumas nuances com relação à conversão de strings para listas e de listas para strings. Nos exemplos acima, convertemos uma string (“Ordem e Progresso”) em uma lista de caracteres, e ao imprimir a lista vemos que a representação da string muda (ela passa a ser uma lista de caracteres). No exemplo seguinte, convertemos a lista de caracteres de volta para uma string usando a função join, e vemos que a representação da string muda novamente (ela volta a ser uma string). Nestes casos, estamos criando novos objetos (strings ou listas) toda vez que convertemos um objeto em outro.

Fique atento a estas diferenças. A sintaxe para se manipular strings seja muito parecida com a sintaxe para se manipular listas. Mas strings e listas são coisas diferentes em Python.

Em algumas situações, desejamos imprimir ou percorrer os elementos de uma lista em uma ordem específica. Para isso, podemos ordenar a lista. Python provê métodos para isso, conforme mostrado nos seguintes exemplos:

# Ordenando listas.
lista = [7, 25, 2, 3, 30, 7, 80, 100, -1, 15]
print("Lista não ordenada: ", lista)

lista.sort()
print("Lista ordenada: ", lista)

lista.sort(reverse=True)
print("Lista ordenada em ordem decrescente: ", lista)
Lista não ordenada:  [7, 25, 2, 3, 30, 7, 80, 100, -1, 15]
Lista ordenada:  [-1, 2, 3, 7, 7, 15, 25, 30, 80, 100]
Lista ordenada em ordem decrescente:  [100, 80, 30, 25, 15, 7, 7, 3, 2, -1]

Os exemplos acima mostram como ordenar listas em Python de forma forma que chamamos in place. Isso quer dizer que a lista foi ordenada sem que espaço adicional fosse usado.

Python nos permite também ordenar uma cópia da lista original e retornar essa cópia ordenada da lista. Assim, a lista original permanece inalterada e uma nova lista ordenada é criada e retornada. Veja como isso funciona:

# Ordenando listas.
lista = [7, 25, 2, 3, 30, 7, 80, 100, -1, 15]
print("Lista original antes da ordenação: ", lista)

lista_ordenada = sorted(lista)
print("Lista ordenada: ", lista_ordenada)

print("A lista original permanece inalterada: ", lista)
Lista original antes da ordenação:  [7, 25, 2, 3, 30, 7, 80, 100, -1, 15]
Lista ordenada:  [-1, 2, 3, 7, 7, 15, 25, 30, 80, 100]
A lista original permanece inalterada:  [7, 25, 2, 3, 30, 7, 80, 100, -1, 15]

A menos que você precise tanto da lista original quanto de uma cópia dessa lista ordenada, recomenda-se o uso da ordenação in place, uma vez que ela não cria uma lista nova, e portanto usa menos espaço em memória.

Modificando Listas

Em algumas situações, é preciso adicionar, remover ou modificar elementos em uma lista. Python nos provê recursos para fazer essas coisas. Veja:

# Cria uma lista vazia.
lista = []

# Adiciona elementos no final da lista.
lista.append("P")
lista.append("Y")
lista.append("T")
lista.append("H")
lista.append("O")
lista.append("N")

print(lista)
['P', 'Y', 'T', 'H', 'O', 'N']

É possível modificar elementos em uma lista. Dizemos que listas são tipos de dados mutáveis. Este conceito ficará mais interessante quando estudarmos tuplas, que são tipos de dados imutáveis.

lista[1] = 'A'
lista[3] = 'R'
lista[4] = 'I'
lista[5] = 'A'

print(lista)
['P', 'A', 'T', 'R', 'I', 'A']

A função append sempre insere elementos no final da lista. Isso é bom por questões de desempenho. É mais rápido inserir elementos no final de uma lista porque não precisamos percorrer a lista procurando a posição onde o elemento deve ser inserido. Mas também é possível inserir elementos em posições específicas da lista, usando a função insert.

lista = ['P', 'T', 'H', 'N']
lista.insert(1, "Y")
lista.insert(4, "O")

print(lista)
['P', 'Y', 'T', 'H', 'O', 'N']

Como dissemos antes, listas são mutáveis, logo, é possível remover elementos delas.

lista = ['A', 'S', 'C', 'E', 'N', 'D', 'E', 'R']
print("Lista original: ", lista)

lista.remove("S")
print("Removendo um elemento: ", lista)
Lista original:  ['A', 'S', 'C', 'E', 'N', 'D', 'E', 'R']
Removendo um elemento:  ['A', 'C', 'E', 'N', 'D', 'E', 'R']

Para remover um elemento em uma posição específica, usamos del. Note a diferença em relação à função remove, que recebe como parâmetro o valor que desejamos remover.

lista = ['A', 'S', 'C', 'E', 'N', 'D', 'E', 'R']
print("Lista original: ", lista)

del lista[1]
print("Removendo um elemento: ", lista)
Lista original:  ['A', 'S', 'C', 'E', 'N', 'D', 'E', 'R']
Removendo um elemento:  ['A', 'C', 'E', 'N', 'D', 'E', 'R']

Para mais detalhes sobre o funcionamento de listas em Python, digite help(list) na linha de comandos do interpretador Python.

Tuplas

Tuplas são parecidas com listas, mas tuplas são imutáveis: uma vez que você cria uma tupla, você não pode modificá-la de nenhuma forma, ou seja, não pode alterar um elemento da tupla, não pode inserir elementos, e não pode remover elementos.

A sintaxe de criação de tuplas é (..., ..., ...), ou ..., ..., conforme mostrado nos exemplos abaixo.

# Exemplo de criação de tuplas.

tupla_vazia = () # Também é possível fazer: tupla_vazia = tuple()
print("Tupla vazia: ", tupla_vazia)

coordenada = (10, 20)
print("Exemplo de tupla: ", coordenada)

print("Tipo de uma tupla: ", type(coordenada))

lat, long = 31.79, 56.14
print("Outro exemplo de criação de tupla: ", (lat, long))
Tupla vazia:  ()
Exemplo de tupla:  (10, 20)
Tipo de uma tupla:  <class 'tuple'>
Outro exemplo de criação de tupla:  (31.79, 56.14)

Podemos fazer o caminho inverso e “desempacotar” uma tupla:

x, y = coordenada
print("x =", x)
print("y =", y)
x = 10
y = 20

Como dissemos, tuplas não podem ser modificadas. Veja o que acontece quando tentamos modificar uma tupla:

coordenada[0] = 15
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-216-94c38671ad7b> in <module>()
----> 1 coordenada[0] = 15


TypeError: 'tuple' object does not support item assignment

Um uso interessante de tuplas é a troca dos valores de duas variáveis. Essa operação é comumente conhecida como swap. Vejamos um exemplo:

x = 10
y = 20

# Swap errado.
print("x e y antes do swap: ", x, y)

x = y
y = x

print("x e y depois do swap (errado): ", x, y)
x e y antes do swap:  10 20
x e y depois do swap (errado):  20 20

Você consegue identificar o problema no código acima?

Vejamos agora formas corretas de fazer o swap do conteúdo de duas variáveis.

x = 10
y = 20

# Swap tradicional.
print("x e y antes do swap: ", x, y)

temp = x
x = y
y = temp

print("x e y depois do swap: ", x, y)


x = 10
y = 20

# Swap com tuplas.
print("x e y antes do swap: ", x, y)

x, y = y, x

print("x e y depois do swap: ", x, y)
x e y antes do swap (tradicional):  10 20
x e y depois do swap (tradicional):  20 10
x e y antes do swap (usando tuplas):  10 20
x e y depois do swap (usando tuplas):  20 10

Dicionários

Dicionários em Python são conjuntos de chave-valor. A sintaxe para criação de dicionários em Python é {chave1 : valor1, chave2 : valor2, ...}.

# O comando dicionario_vazio = dict() possui o mesmo efeito do comando abaixo.
dicionario_vazio = {}
print("Dicionário vazio: ", dicionario_vazio)

paises = {'BRA': 'Brasil', 'EUA': 'Estados Unidos', 'FRA': 'França'}
print("Exemplo de dicionário: ", paises)

print("Tipo de um dicionário: ", type(paises))
Dicionário vazio:  {}
Exemplo de dicionário:  {'BRA': 'Brasil', 'EUA': 'Estados Unidos', 'FRA': 'França'}
Tipo de um dicionário:  <class 'dict'>

Ao contrário de tuplas, dicionários podem ser modificados:

# Modificando um dicionário.
paises["BRA"] = "Brazil"
paises["FRA"] = "France"

# Adicionando um elemento.
paises["ESP"] = "Espanha"

print("Dicionário modificado: ", paises)
Dicionário modificado:  {'BRA': 'Brazil', 'EUA': 'Estados Unidos', 'FRA': 'France', 'ESP': 'Espanha'}

Dicionários nos permitem pesquisar facilmente por valores quando sabemos a chave correspondente:

print("EUA: ", paises['EUA'])
EUA:  Estados Unidos