Funcionais sobre listas
Quando utilizamos listas é comum fazer uso de vários funcionais, i.e., funções que recebem por parâmetro outras funções. Estes funcionais podem ser transformações, filtros ou acumuladores.
Nota-se que existem já um número significativo de funcionais em Python. Entre os mais comuns temos o filter, o map e o reduce, este último disponível no módulo functools. Estes podem ser utilizados sobre qualquer iterável e não apenas sobre listas.
Devemos também referir que este tipo de operadores sobre colecções são também comuns entre as novas plataformas de processamento de grandes volumes de dados. A título de exemplo, dado que também suporta Python, referimos a plataforma Apache Spark. Nota-se em particular o conjunto de transformações disponíveis, em particular em Python através do pacote pyspark.
Transformações
Uma transformação ou transformador recebe com argumentos uma lista e uma função aplicável sobre cada elemento na lista. Devolve uma lista em que cada elemento resulta da aplicação da função a cada elemento da lista original. Em geral a lista original não é modificada, sendo retornada uma nova lista.
Exemplo de implementação deste funcional:
def transforma(f, lst):
res = []
for x in lst:
res = res + [f(x)]
return resExemplo de utilização e paralelo com função pré-definida map:
>>> transforma(lambda x : x*x, [2, 3, 5, 7]) [4, 9, 25, 49] >>> map(lambda x : x*x, [2, 3, 5, 7]) <map object at 0x3ae62539f60> >>> list(map(lambda x : x*x, [2, 3, 5, 7])) [4, 9, 25, 49] >>> map(lambda x,y : x*x + y, [2, 3, 5, 7], [1, 2, 3, 4]) <map object at 0x3ae62542128> >>> list(map(lambda x,y : x*x + y, [2, 3, 5, 7], [1, 2, 3, 4])) [5, 11, 28, 53] >>> l = [2, 3, 5, 7] >>> transforma(lambda x : x*x, l) [4, 9, 25, 49] >>> l [2, 3, 5, 7] >>> list(map(lambda x,y : x*x + y, l, l)) [6, 12, 30, 56] >>> l [2, 3, 5, 7] >>>
Neste exemplo podemos ver que a função map não retorna uma lista, mas sim um objecto que é iterável.
Filtros
Um filtro é um funcional que recebe uma lista e um predicado aplicável sobre cada elemento da lista. Devolve a lista constituída apenas pelos elementos da lista original que satisfazem o predicado, i.e., os elementos para os quais o predicado retorna True. Em geral a lista original não é modificada, sendo retornada uma nova lista.
Exemplo de implementação deste funcional:
def filtro(p, lst):
res = []
for x in lst:
if p(x):
res = res + [x]
return resExemplo de utilização e paralelo com função pré-definida filter
>>> filtro(lambda x : x%2 == 0, [0, 1, 1, 2, 3, 5, 8]) [0, 2, 8] >>> filter(lambda x : x%2 == 0, [0, 1, 1, 2, 3, 5, 8]) <filter object at 0x3ae6255c5f8> >>> list(filter(lambda x : x%2 == 0, [0, 1, 1, 2, 3, 5, 8])) [0, 2, 8] >>> l = [0, 1, 1, 2, 3, 5, 8] >>> filtro(lambda x : x%2 == 0, l) [0, 2, 8] >>> list(filter(lambda x : x%2 == 0, l)) [0, 2, 8] >>> l [0, 1, 1, 2, 3, 5, 8] >>>
Neste exemplo podemos ver que a função filter não retorna uma lista, mas sim um objecto que é iterável.
Acumuladores
Um acumulador recebe uma lista e um função aplicável aos elementos da lista. Aplica sucessivamente essa função aos elementos da lista e devolve o resultado da aplicação da mesma a todos os elementos. Nota-se que a função passada ao acumulador recebe em geral dois parâmetros, o resultado actual e o próximo elemento, devolvendo o valor resultante de incluir esse elemento no cálculo do resultado.
Exemplo de implementação deste funcional:
def acumulador(f, lst):
res = lst[0]
for x in lst[1:]:
res = f(res, x)
return resExemplo de utilização e paralelo com função reduce do módulo functools:
>>> acumulador(lambda r,x : r * x, [2, 3, 5, 7]) 210 >>> from functools import reduce >>> reduce(lambda r,x : r * x, [2, 3, 5, 7]) 210 >>>
Mais exemplos
>>> conversor = lambda b: reduce(lambda x,y: x+y, list(map(lambda x, y: (ord(x) - ord('0'))*2**y, b, range(len(b)-1,-1,-1))))
>>> conversor('101')
5
>>> conversor('1')
1
>>> conversor('11110110')
246
>>>
>>> somadigitos = lambda n : reduce(lambda x,y: x+y, map(lambda x: ord(x) - ord('0'), str(n)))
>>> somadigitos(89)
17
>>> somadigitos(89192)
29
>>>
>>> somadigitos = lambda n : reduce(lambda x,y: x+y, filter(lambda x: x%2, map(lambda x: ord(x) - ord('0'), str(n))))
>>> somadigitos(89192)
19
>>>