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 res
Exemplo 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 res
Exemplo 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 res
Exemplo 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 >>>