Em aulas anteriores e nos EPs, vimos tipos de dados para lidar com coleções sequenciais, nas quais os elementos na coleção estão ordenados da esquerda para a direita e os seus valores são acessados por meio de índices que são números inteiros. As listas (list
), as strings (str
) e as tuplas (tuple
) são coleções sequenciais.
Agora veremos um outro tipo de dados do python - o dict
(de dictionary, ou dicionário em português) - que também é usado para representar coleções. Entretanto, em um dict
a organização dos elementos não é sequencial.
Um dicionário é um tipo abstrato de dados que associa uma chave a um valor. A chave precisa ser única, ou seja, não pode haver chaves repetidas dentro do dicionário. A chave também deve ser imutável, ou seja, uma vez criada, ela permanece a mesma. Portanto, pode-se usar como chave strings, números e tuplas, mas não listas. Já o valor pode ser de qualquer tipo do python.
Para criar um dicionário vazio chamado dic
, você pode fazer:
dic = {}
Observe que os elementos de um dicionário são delimitados por chaves ({}
), enquanto que os itens de uma lista são delimitados por colchetes ([]
).
Para criar um dicionário já com elementos dentros, basta colocar os elementos entre as chaves separados por vírgulas, e usando :
(dois pontos) para separar a chave do valor, como mostrado no exemplo abaixo:
disciplinas = {'MAC2166':'Introdução à Computação', 'MAT2453':'Cálculo Diferencial e Integral I'}
print("O conteúdo do meu dicionário de disciplinas é:\n", disciplinas)
Para ler, criar ou modificar um elemento do dicionário, temos que usar a chave do elemento entre colchetes, como nos exemplos abaixo:
estoque = {'banana':50, 'maçã':4, 'abacaxi':10} # cria um dicionário com 3 elementos
print("Dicionário inicial:", estoque)
estoque['melancia'] = 7 # adiciona no dicionário um novo elemento: o valor 7 associado à chave 'melancia'
print("Dicionário depois da adição de novo elemento:", dic)
estoque['banana'] += 15 # modifica o valor assocido à chave 'banana'
print("Dicionário depois da modificação do valor de um elemento:", estoque)
print("Valor associado à chave 'abacaxi' no dicionário:", estoque['abacaxi']) # lê o valor associado à 'abacaxi'
Quando tentamos obter o valor associado à uma chave que não existe no dicionário, uma exceção do tipo KeyError
é gerada (veja o exemplo abaixo):
estoque = {'banana':50, 'maçã':4, 'abacaxi':10}
print(estoque['pera'])
Podemos verificar se uma dada chave existe em um dicionário usando o operador in
, ou ainda verificar se uma chave não existe no dicionário usando not in
. Veja o exemplo abaixo:
estoque = {'banana':50, 'maçã':4, 'abacaxi':10}
if 'pera' in estoque: # verifica se a chave 'pera' existe no dicionário estoque
print("A quantidade de peras no estoque é:", estoque['pera'])
else:
print("Não vendemos peras!")
if 'abacate' not in estoque:
print("E também não vendemos abacates.")
Há diferentes formas de se percorrer todos os elementos de um dicionário usando um laço for
. Podemos usar o for
para iterar sobre as chaves contidas no dicionário e, a partir de cada chave, acessar o valor associado a ela no dicionário. Veja abaixo um exemplo disso:
estoque = {'banana': 50, 'laranja': 12, 'melancia': 7, 'kiwi': 23}
for chave in estoque:
valor = estoque[chave]
print("Temos %d unidades de %s no estoque."%(valor, chave))
Uma forma menos compacta para se iterar sobre as chaves de um dicionário (mas talvez mais legível para alguns) é usando o método keys()
de dict
, como mostrado abaixo:
for chave in estoque.keys():
valor = estoque[chave]
print("Temos %d unidades de %s no estoque."%(valor, chave))
É possível também iterar sobre os valores de um dicionário utilizando o método values()
de dict
. Assim, para saber quantas frutas há no estoque podemos escrever:
total = 0
for valor in estoque.values():
total += valor
print("Temos %d frutas no estoque."%(total))
Por fim, é possível iterar sobre os pares (chave,valor) de um dicionário usando o método items()
de dict
. Veja o exemplo abaixo:
for (fruta,quantidade) in estoque.items():
print("Temos %d unidades de %s no estoque."%(quantidade, fruta))
O conteúdo apresentado nesta aula é baseado no material disponível aqui e também aqui.
def main():
frase = input("Digite uma frase:\n")
freq_letras = {} # cria um dicionário vazio
for caractere in frase: # para cada caractere na frase, faça
if caractere not in ' .,;:?!\t\n': # se o caractere atual não é um caractere que deve ser ignorado
if caractere in freq_letras: # verifica se o caractere já está no dicionário
freq_letras[caractere] += 1 # Sim, então incrementa a sua frequência
else:
freq_letras[caractere] = 1 # Não, então inclui o caractere no dicionário,
# indicando 1 como frequência
for (letra,freq) in freq_letras.items():
print("A frequência da letra '%c' na frase é %d" %(letra, freq))
main()
Matrizes esparsas tipicamente possuem zero em quase todas as posições, e valores diferentes de zero em apenas algumas posições.
Uma matriz esparsa pode ser representada como um dicionário, utilizando as coordenadas como chave.
Por exemplo, a matriz esparsa abaixo
0 | 0 | 0 | 0 | 5 |
0 | 13 | 0 | -1 | 0 |
0 | 0 | 0 | 0 | 0 |
0 | 0 | 42 | 0 | 0 |
poderia ser representada pelo seguinte dicionário em python:
mat_esparsa = {(0,4):5, (1,1):13, (1,3):-1, (3,3):42}
for (coordenada,valor) in mat_esparsa.items():
print("A posição", coordenada, "da matriz esparsa contém o valor ", valor)
Como exemplo, vamos implementar um jogo de batalha naval onde o mapa será representado como uma matriz esparsa mantida em um dicionário, com:
O “mar” onde estão as embarcações tem coordenadas de 0 a 99, tanto no eixo x quanto no eixo y.
A partir do esqueleto abaixo, escreva um programa que carrega um mapa em um dicionário usando a função dada carrega_mapa
e leia coordenadas do usuário até que ele desista ou até que não reste mais pontos para serem ganhos (ou seja, até que ele afunde todas as embarcações).
Para facilitar a detecção do fim do jogo, implemente uma função total_pontos
que retorna o total de pontos ainda disponível no dicionário.
Antes de terminar o programa, imprima quantos pontos o usuário ganhou.
def main():
# edite o código abaixo para resolver este exercício
mapa = carrega_mapa()
print(mapa)
def total_pontos( dic ):
''' (dict) -> int '''
# escreva a função
def carrega_mapa():
''' Retorna um dicionário contendo as coordenadas das
embarcações. O mapa poderia ser lido, por exemplo, de um
arquivo, ou as posições das embarcações poderiam ser
sorteadas.
Na implementação atual, o mapa está fixo.
'''
return {(2,5):100, # submarino
(20,60):30, (21,60):30, # cruzador
(42,71):20, (43,71):20, (44,71):20, (45,71):20} # porta-aviões
main()
Na estratégia de implementação mostrada abaixo, modifica-se o valor associado a uma posição definida no dicionário para zero toda vez que o usuário acertar uma embarcação.
def main():
mapa = carrega_mapa()
fim = False
pontos = 0
total = total_pontos(mapa)
print("Batalha Naval")
print("Você pode fazer até %d pontos\n"%total)
print("Digite as coordenadas separadas por vírgula")
while not fim:
x, y = input("Digite x, y (ou -1,-1 para terminar): ").split(',')
x, y = int(x), int(y)
print("Você jogou em: %d,%d" %(x,y))
if (x,y) == (-1,-1):
# Usuário pediu para encerrar o jogo
fim = True
elif (x,y) in mapa and mapa[x,y] > 0:
# (x,y) é a coordenada de um pedaço de embarcação ainda não atingido
valor = mapa[x,y]
print("Voce acertou uma embarcação e fez %d pontos" %valor)
pontos += valor
mapa[(x,y)] = 0 # troca o valor da posição para zero para indicar que foi atingida
if total_pontos(mapa) == 0:
# Usuário já ganhou todos os pontos possíveis
fim = True
else:
print("Água!!")
print("Você fez %d pontos" %pontos)
#----------------------------------------------------
def total_pontos(dic):
''' (dict) -> int '''
soma = 0
for coordenada in dic:
soma += dic[coordenada]
return soma
#----------------------------------------------------
def carrega_mapa():
''' Retorna um dicionário contendo as coordenadas das
embarcações. O mapa poderia ser lido, por exemplo, de um
arquivo, ou as posições das embarcações poderiam ser
sorteadas.
Na implementação atual, o mapa está fixo.
'''
return {(2,5):100, # submarino
(20,60):30, (21,60):30, # cruzador
(42,71):20, (43,71):20, (44,71):20, (45,71):20} # porta-aviões
#----------------------------------------------------
main()