Às vezes precisamos realizar a contagem do número de aparições de determinados elementos em uma sequência, como uma string ou uma lista. Por exemplo, quero saber quantas vezes cada letra apareceu em uma string. Como fazer isso em Python? Primeiro, vamos fazer “na mão” e depois vamos conhecer uma solução “pronta”.
def conta_ocorrencias(s):
ocorrencias = {}
for c in s:
if c in ocorrencias:
ocorrencias[c] = ocorrencias[c] + 1
else:
ocorrencias[c] = 1
return ocorrencias
A solução acima apresentada utiliza um dicionário armazenando como chaves as letras encontradas e, como valor para cada letra, a quantidade de ocorrências desta. Percorremos a string s letra por letra e, se a letra atual já estiver sendo usada como chave no dicionário ocorrencias, o valor correspondente a tal letra é incrementado em um (ou seja, encontramos mais uma ocorrência da letra na string recebida). Se a letra ainda não estiver aparecendo como chave do dicionário, então é criada uma entrada neste com a letra sendo usada como chave e o valor associado 1 (ocorrencias[c] = 1). Vamos analisar o teste feito dentro do for:
...
if c in ocorrencias:
ocorrencias[c] = ocorrencias[c] + 1
else:
ocorrencias[c] = 1
...
Esse teste é necessário porque se tentarmos acessar uma chave inexistente de um dicionário, é retornado um KeyError. Assim, precisamos testar para verificar se a letra atual já foi anteriormente inserida no dicionário ou não. Se foi, daí sim podemos incrementar o valor associado. Se não foi, daí temos que incluir tal valor com o número 1 associado.
Para simplificar isso, podemos usar o módulo collections [1]. Esse módulo nos fornece um tipo especial de dicionário chamado de defaultdict [2]. Esse dicionário permite que especifiquemos, ao construir um dicionário, uma função que será chamada para retornar um valor padrão para quando a chave solicitada não existir no dicionário. Com ele, é possível fazer o seguinte:
ocorrencias = collections.defaultdict(int)
...
ocorrencias[c] = ocorrencias[c] + 1
...
A função int(), quando chamada sem argumentos, retorna 0. Como passamos ela ao construtor do dicionário ocorrências, é ela que será chamada quando houver um acesso a uma chave inexistente. Isso possibilita que usemos esse valor para fazer a soma no código acima. Na primeira vez que é executado para determinado caractere, o código acima será executado como se fosse:
ocorrencias[c] = 0 + 1
Nas vezes seguintes, ao invés de 0 (valor obtido ao tentarmos acessar o valor de uma chave inexistente), teremos como valor o número atual de ocorrências para o caractere contido na variável c. O código completo segue abaixo:
import collections
def conta_ocorrencias(s):
ocorrencias = collections.defaultdict(int)
for c in s:
ocorrencias[c] = ocorrencias[c] + 1
return ocorrencias
E a solução “pronta”?
O jeito mais simples de fazer a contagem de ocorrências dos elementos de uma sequência é através da classe Counter [3], também presente no módulo collections. Vamos ver um exemplo de utilização:
>>> import collections
>>> s = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut"
>>> c = collections.Counter(s)
>>> print c.most_common(5)
[(' ', 13), ('i', 11), ('e', 8), ('t', 8), ('d', 7)]
Um dos métodos mais interessantes é o most_common() [4], que retorna uma lista contendo os elementos mais comuns na sequência. Se passarmos um número n como argumento, ele irá retornar os n valores mais comuns na sequência, como no exemplo acima.
Além do Counter e do defaultdict, o módulo collections fornece várias outras estruturas úteis, que veremos em posts futuros.
[1] http://docs.python.org/library/collections.html
[2] http://docs.python.org/library/collections.html#collections.defaultdict
[3] http://docs.python.org/library/collections.html#collections.Counter
[4] http://docs.python.org/library/collections.html#collections.Counter.most_common