DICIONÁRIOS CHRISTOPHER FREIRE SOUZA EWERTON AMORIM DE OLIVEIRA

Slides:



Advertisements
Apresentações semelhantes
Recursividade, Entrada pelo teclado e Funções com retorno Dilvan Moreira.
Advertisements

INE5408 Estruturas de Dados Ponteiros, passagem de parâmetros e modelos de memória.
Introdução à Informática com Software Livre 12:58.
Princípios de Desenvolvimento de Algoritmos MAC122 Prof. Dr. Paulo Miranda IME-USP Variáveis e Atribuições.
Algoritmos e Programação utilizando Visualg
Aula 3 - Estruturas de Repetição
Gladius Acesso Treinamento.
Estudo de caso: Seleção de estrutura de dados
LibreOffice - Calc Fórmulas e Funções
FUNÇÕES EWERTON AMORIM DE OLIVEIRA LUCAS HENRIQUE SILVA
Contagem Aula 2, ciclo 3.
Recursividade, Entrada pelo teclado e Funções com retorno
Algoritmos e Estruturas de Dados I
Tuplas CHRISTOPHER FREIRE SOUZA EWERTON AMORIM DE OLIVEIRA
MdC e MMC Aula 1, ciclo 3.
Introdução à Programação Linguagem C
ESTRUTURA DE DADOS Professor: Marcelo Mendes Turma: MBI-1
LISTAS CHRISTOPHER FREIRE SOUZA EWERTON AMORIM DE OLIVEIRA
EWERTON AMORIM DE OLIVEIRA LUCAS HENRIQUE SILVA
Estruturas de Decisão.
IP – Listas Prof. Eduardo Falcão.
Introdução à Computação para Engenharia MAC2166
Introdução ao VisuALG Prof. Andrew Rodrigues
Módulo I Capítulo 2: IDE e Variáveis
Introdução a Programação
Linguagem C Para programadores Python
Prof. Wellington Franco Sub-Rotinas:Funções e Procedimentos
3.1 Classes e Objetos Em um programa orientado a objetos normalmente existem vários objetos de um mesmo tipo. Por exemplo, um programa de controle de.
Algoritmos e Estruturas de Dados I
Estruturas de Repetição
Prof. Wellington Franco
FUNDAMENTO DE PROGRAMAÇÃO
M.d.c. algoritimo de Euclides
POO - Classes Dilvan Moreira.
CES-11 ALGORITMOS E ESTRUTURAS DE DADOS Aulas Práticas
Coleções: Listas Dilvan Moreira.
INF1007: Programação Funções Recursivas
Estrutura de dados Pilhas e filas
FUNDAMENTO DE PROGRAMAÇÃO PROF. BRUNO DE CASTRO H. SILVA
FUNDAMENTOS DE PROGRAMAÇÃO
FUNDAMENTO DE PROGRAMAÇÃO PROF. BRUNO DE CASTRO H. SILVA
ARRAYS Dilvan Moreira (baseado no livro Big Java e T. Munzner)
FUNDAMENTO DE PROGRAMAÇÃO
CONCEITO DE VARIÁVEIS ESTÁTICAS
FEUP/LEEC Algoritmos e Estruturas de Dados 2001/2002
FUNDAMENTO DE PROGRAMAÇÃO PROF. WELLINGTON FRANCO
Algoritmos e Estruturas de Dados I
Algoritmos e Técnicas CEFET/RN.
Introdução à Programação
IP – Repetições for Prof. Eduardo Falcão.
PROGRAMAÇÃO I UNIDADE 3.
Tecnologia para Internet - II
Módulo I Capítulo 4: Operador de Repetição
Estudo de caso: Interface de função
Aula 22 Modularização 22/10/08.
Prof.: Carlos Alberto Algoritmos Prof.: Carlos Alberto
Curso básico de PHP. 1 Vantagens: Gratuito Multiplataforma Estável Rapidez Comunicação.
Computação Eletrônica Vetores e Matrizes
Algoritmos e Estruturas de Dados I – Ponteiros
Estruturas de Dados em C
Representação de Algoritmos
Tipos Primitivos de Dados
Python: Recursão Claudio Esperança.
Introdução a progrmação Comandos condicionais: if e switch
Aula 11 Professores: Conteúdo: Dante Corbucci Filho
Estruturas Condicionais
RESULUÇÃO DOS EXERCÍCIOS E
JAVA - BÁSICO COL. ESTADUAL MARIA AGUIAR TEIXEIRA
Aula 8 Professores: Conteúdo: Dante Corbucci Filho
Aula 2 Professores: Conteúdo: Dante Corbucci Filho
Transcrição da apresentação:

DICIONÁRIOS CHRISTOPHER FREIRE SOUZA EWERTON AMORIM DE OLIVEIRA LUCAS HENRIQUE SILVA

Caso de estudo: Seleção estruturada de dados Acesse o Projeto Gutenberg e baixe seu livro favorito sem direitos autorais no format de texto simples. Crie um programa para contar o número de palavras no livro e quantas vezes cada palavra se repete. Crie um histograma com as 20 palavras mais utilizadas no livro.

Dicionários são mapeamentos Dicionários são parecidos com listas, porém em listas os índices tem que ser inteiros, já em dicionários os índices podem ser de vários tipos. Um dicionário contém uma coleção de índices, que são chamados de chaves (keys) e uma coleção de valores (values). Cada chave está associada a um único valor (ou coleção). A associação de uma chave a um valor é chamada de par chave-valor ou às vezes de ítem. Na linguagem matemática, um dicionário representa um mapeamento de chaves a valores, então você também pode dizer que cada chave “mapeia” um valor.

Dicionários são mapeamentos Como um exemplo, vamos contruir um dicionário que mapeia palavras do inglês para o português, desta forma as chaves e valores serão strings. As chaves “{}” representam um dicionário vazio. Para adicionar itens no dicionário você pode utilizar colchetes. Esta linha cria um ítem que mapeia a chave “one” para o valor “um”. >>> eng_2_pt = dict() >>> eng_2_pt {} >>> eng_2_pt[“one”] =“um”

Dicionários são mapeamentos Se imprimirmos novamente o dicionário podemos ver o ítem com dois pontos separando a chave do valor. Este formato de saída serve também como formato de entrada. Podemos criar um dicionário da seguinte forma: Se você imprimir novamente o dicionário, você pode estranhar algo. A ordem que um dicionário se organiza normalmente é imprevisível. Mas não tem problema porque os índices dos dicionário nunca são inteiros. >>> eng_2_pt {‘one’ : ‘um’} >>> eng_2_pt = {'one': 'um', 'two': 'dois', 'three': 'três‘}

Acessando um valor de um dicionário Você usa as chaves para procurar pelos valores correspondentes: A chave “one” sempre acessa o valor “um”, não importa a ordem dos itens. Agora tente: Note que você obteve uma exceção, isto sempre acontece quando você tenta acessar uma chave que ainda não tem no dicionário. >>> eng_2_pt[“one”] ‘um’ >>> eng_2_pt[“four”]

Mais sobre dicionários A função len() funciona em dicionários. O operador in também funciona para dicionários Note que este operador só funciona para chaves, para utilizar o operador para os valores, utilize o método .values() de dicionários. >>> len(eng_2_pt) 3 >>> “one” in eng_2_pt True >>> “um” in eng_2_pt False >>> “um” in eng_2_pt.values() True

Mais sobre dicionários O operador in funciona com algoritmos diferentes para dicionários e para listas. Para listas ele pesquisa elementos em ordem. Quanto maior a lista, maior o tempo de execução. Para dicionários, o operador utiliza o algoritmo conhecido como “hashtable”, em que o operador pega os itens num mesmo intervalo de tempo, não importa a quantidade.

Dicionários como uma coleção de contadores Suponha que você tenha uma string e você quer contar quantas vezes cada letra aparece. Existem várias formas de fazer isso. Você consegue pensar em alguma? Veja algumas delas: Você poderia criar 26 variáveis, cada uma representando uma letra do alfabeto. Então você percorreria uma string e, para cada caractere, incrementaria a quantidade correspondente, provavelmente utilizando condicionais encadeadas. Você poderia criar uma lista com 26 elementos contendo as letras do alfabeto e converter cada letra em um inteiro utilizando a função ord() e utilizar estes índices em uma lista para fazer a contagem. Você poderia criar um dicionário com caracteres como chaves e as quantidades de cada caractere como valores. A primeira vez que você ver um caractere na string, você adiciona o ítem no dicionário. Depois você poderia incrementar o valor para caracteres existentes.

Dicionários como uma coleção de contadores Cada uma das opções leva ao mesmo resultado, mas cada uma obtém os resultados por diferentes caminhos. Uma implementação é um caminho para um fim. Algumas implementações são melhores que outras. Por exemplo, uma vantagem da implementação com dicionários é que não temos que saber antes do tempo quais letras aparecem na string e nós apenas temos que abrir espaço para as letras que realmente aparecem. Veja a seguir como o código seria: def histograma(s): d = dict() for c in s: if c not in d: d[c] = 1 else: d[c]+=1 O nome desta função é histograma, que é um termo estatístico que representa uma coleção de quantidades, ou frequências

Dicionários como uma coleção de contadores O método .get() Este método recebe como argumento uma chave e um valor padrão. Se a chave aparece no dicionário, a função retorna o valor correspondente. Se não existir, a função retorna o valor padrão. Como exercício, altere a função histograma para eliminar a condição. >>> h = histograma('a') >>> h {'a': 1} >>> h.get('a', 0) 1 >>> h.get('b', 0)

Loopings e dicionários Se você usa um dicionário em um estrutura de repetição for, a estrutura percorrerá todas as chaves do dicionário. Por exemplo, a função imprime_histograma() imprime cada chave do dicionário, seguido por seus respectivos valores. Como dito anteriormente, os dicionários não são ordenados. Para acessar as chaves de forma ordenada, utilize a função sorted(). def imprime_histograma(h): for c in h: print(c, h[c]) for key in sorted(h): print(key, h[key])

Procura reversa (Reverse lookup) Dado um dicionário d e uma chave k, é fácil encontrar o valor correspondente v = d[k], esta operação é chamada de lookup (procura) E se você tiver um dicionário e um valor v e quiser achar a chave correspondente? Você tem 2 problemas: Pode existir mais de uma chave que mapeia um valor v. Dependendo da aplicação, você pode pegar 1 ou fazer uma lista que contém todas as chaves. Não existe uma sintaxe simples pra fazer isso, você tem que fazer uma pesquisa.

Procura reversa (Reverse lookup) A seguinte função pega o valor e retorna a primeira palavra que mapeia o valor: Esta é uma função com uma pesquisa comum, mas contém uma característica diferente, o raise. A declaração raise causa uma exceção. Neste caso, causa um LookupError que é uma exceção que já vem no Python, observe que não precisamos importar. Esta exceção serve para indicar quando uma operação de pesquisa falhou. def procura_reversa(d, v): for k in d: if d[k] == v: return k raise LookupError()

Procura reversa (Reverse lookup) Teste a função para os seguintes casos e veja o que acontece: O efeito que a declaração raise causa é a mesma quando o Python causa uma exceção. Você pode criar uma mensagem e erro. >>> h = histograma (‘amarelo’) >>> chave = procura_reversa (h, 2) >>> chave = procura_reversa (h, 3) >>> raise LookupError(‘Este valor não aparece no dicionário')

Dicionários e Listas Uma lista pode aparecer como um valor de dicionário. Se você tem um dicionário que mapeia de letras para frequências, você pode querer inverter isso, criando um dicionário que mapeia de frequências para letras. Pode existir muitas letras com a mesma frequência. Assim, cada valor será uma lista de letras no dicionário invertido. def inverte_dicionario(d): inverso = dict() for chave in d: val = d[chave] if val not in inverso: inverso[val] = [chave] else: inverso[val].append(chave) return inverso Lembre-se de utilizar o Python Tutor para entender o que está acontecendo.

Dicionários e Listas Tente utilizar listas como chaves e veja o que acontece. Tente utilizar um dicionário como chave de outro e veja o que acontece. Agora tente utilizar um dicionário como valor de outro.

MEMOS Se você já fez a função recursiva Fibonacci deve ter percebido que a função demora muito para executar com números grandes. Para entender o porquê, considere a figura a seguir – Gráfico de chamada da função:

MEMOS Cada célula dessa é uma execução da função fibonnaci(). Note quantas vezes foi chamada fibonacci(0) e fibonacci(1), por exemplo. Uma solução é guardar em um dicionário todas os valores já calculados. Veja abaixo uma versão “memorizada” de Fibonacci: conhecido = {0:0, 1:1} def fibonacci(n): if n in conhecido : return conhecido[n] res = fibonacci(n-1) + fibonacci(n-2) conhecido[n] = res return res

Variáveis globais Note que no exemplo anterior, a variável conhecido foi colocada fora da função e ela não foi passada como argumento. Ou seja conhecido é uma variável global. Diferente de variáveis locais, que desaparecem quando suas funções terminam, variáveis globais persistem de uma chamada de função para a outra. É comum utilizar variáveis globais como flags; ou seja, variáveis booleanas que indicam quando uma condição é verdadeira. Porém, quando você tenta modificar uma variável global, o resultado pode te surpreender. Veja o exemplo: foi_chamada = False def exemplo(): foi_chamada = True #ERRADO

Variáveis globais Isso acontece por que a função exemplo() cria uma variável local chamada foi_chamada, que vai embora com o termino da execução da função. Para fazer referência a uma variável global dentro de uma função, você deve declarar que é uma variável local. Veja o exemplo: O que a declaração global faz é algo do tipo: “Nesta função, quando eu digo foi_chamada, eu estou me referindo à variável global, não crie uma local!” foi_chamada = False def exemplo(): global foi_chamada foi_chamada = True

Variáveis globais Se a variável global se refere a um valor mutável, você pode modificar o valor sem precisar declarar. Assim, você pode adicionar, remover, ou substituir elementos de uma lista ou dicionário global, mas se você quiser substituir a variável, você deve declarar: conhecido = {0:0, 1:1} def exemplo2(): conhecido[2] = 1 conhecido = {0:0, 1:1} def exemplo2(): global conhecido conhecido = dict()

Números aleatórios Dadas as mesmas entradas, muitos programas computacionais geram a mesma saída toda vez, então estes são chamadas de determinísticos. Determinismo é usualmente uma coisa boa, pois nós esperamos o mesmo cálculo para obter o mesmo resultado. Para algumas aplicações, queremos que o computador seja imprevisível. Jogos são um exemplo óbvio, mas existem outros. Fazer um programa não-determinista acaba sendo difícil, mas existem formas de fazê-lo, pelo menos, algo perto de não-determinista. Um deles utilizam algoritmos que geram números pseudo-aleatórios. Estes números não são aleatórios porque são gerados por algoritmos deterministas.

O módulo random O módulo random promove funções que geram números pseudo- aleatórios (chamaremos de aleatórios daqui em diante para simplificar) A função random() retorna um número real aleatório entre 0.0 e 1.0 Veja o exemplo: A função randint() recebe um intervalo fechado e retorna um inteiro entre eles. for i in range(10): x = random.random() print(x) >>> random.randint(5, 10) 5 9

O módulo random Para escolher um elemento de uma lista aleatoriamente, você pode utilizar a função choice(). >>> t = [1, 2, 3] >>> random.choice(t) 2 3

Caso de estudo: Seleção estruturada de dados Acesse o Projeto Gutenberg e baixe seu livro favorito sem direitos autorais no format de texto simples. Crie um programa para contar o número de palavras no livro e quantas vezes cada palavra se repete. Crie um histograma com as 20 palavras mais utilizadas no livro.

Histograma de palavras Segue o programa que lê um arquivo e cria um histograma com as palavras def processa_arquivo (nome_do_arquivo): hist = dict() fp = open(nome_do_arquivo) for linha in fp: processa_linha(linha, hist) return hist def processa_linha(linha, hist): linha = linha.replace('-', ' ') for palavra in linha.split(): palavra = palavra.strip(string.punctuation + string.whitespace) palavra = palavra.lower() hist[palavra] = hist.get(palavra, 0) + 1 #MAIN hist = processa_arquivo('emma.txt')

Histograma de palavras Para contar o número total de palavras, podemos fazer o seguinte: O número de diferentes palavras é exatamente o número de itens do dicionário: def total_de_palavras(hist): return sum(hist.values()) def different_words(hist): return len(hist)

Palavras mais comuns A seguinte função recebe um histograma e retorna uma lista ordenada com os valores e chaves. Em cada frequência, os valores aparecem primeiro, então a lista está ordenada pela frequência. Segue o programa que imprime as 10 palavras mais comuns: def mais_comuns(hist): t = [] for chave, valor in hist.items(): t.append([valor, chave]) t.sort(reverse=True) return t t = mais_comuns (hist) print(As palavras mais comuns são:') for freq, palavra in t[:10]: print(palavra, freq, sep='\t')

Parâmetros opcionais Você já deve ter percebido que algumas funções do Python recebem parâmetros opcionais como argumento. Também é possível definir funções com parâmetros opcionais. Veja o exemplo: O primeiro parâmetro é obrigatório, o segundo é opcional. def imprime_mais_comuns(hist, num=10): t = mais_comuns(hist) print(As palavras mais comuns são:') for freq, palavra in t[:num]: print(palavra, freq, sep='\t')