2012-09-02 7 views
5

Conoces la práctica función reduce en Python. Por ejemplo, se podría utilizar para resumir una lista como tal (fingir que no es la incorporada en sum):reducelist en Python: como reducir pero dando la lista de resultados intermedios

reduce(lambda x,y: x+y, [1,2,3,4], 0) 

que devuelve (((0 + 1) 2) 3) + 4 = 10.

Ahora, ¿y si quisiera una lista de las sumas intermedias? En este caso, [1,3,6,10].

Aquí hay una solución fea. ¿Hay algo más pitónico?

def reducelist(f, l, x): 
    out = [x] 
    prev = x 
    for i in l: 
    prev = f(prev, i) 
    out.append(prev) 
    return out 
+0

Para su información, al menos en Haskell esto se conoce como * scan *. Reducir también se conoce como (un tipo específico de) * fold * en el mundo de la programación funcional. – delnan

+0

Gracias, Delnan, sí, sé esto como FoldList de Mathematica. Mathematica tiene una versión acumulada de muchas de estas funciones de programación funcional, que se denotan al agregar "Lista". Veo en la respuesta a continuación que en Python 3 lo que llamo reducelist ahora está disponible como accumulate(). – dreeves

Respuesta

8

Mi favorito, si usted es bastante reciente:

Python 3.2.1 (default, Jul 12 2011, 22:22:01) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import itertools 
>>> itertools.accumulate([1,2,3,4]) 
<itertools.accumulate object at 0x1006baad0> 
>>> list(itertools.accumulate([1,2,3,4])) 
[1, 3, 6, 10] 

accumulate también acepta una función argumento [aún más reciente, aunque-- 3.3]:

>>> list(itertools.accumulate([1,2,3,4], lambda x,y: x+y)) 
[1, 3, 6, 10] 
>>> list(itertools.accumulate([1,2,3,4], lambda x,y: x+y+1)) 
[1, 4, 8, 13] 
+0

¡Ah, bien! Aunque para mí esto es demasiado reciente (estoy en Python 2) y demasiado específico (esto es solo para sumar, no es la cosa reductora general que estoy buscando). EDITAR: Ah, es * lo suficientemente general, con ese argumento opcional; ¡Gracias! – dreeves

8

Si haga que su solución para un generador sea más corta y obedezca mejor al estilo de programación funcional. Yo añadiría un valor predeterminado de 0 para x demasiado:

def reducelist(f, lst, x=0): 
    prev = x 
    for i in lst: 
    prev = f(prev, i) 
    yield prev 

Eso es definitivamente más Pythonic.

+0

Gracias! ¿Qué pasa si necesita devolver una lista real? ¿Podemos hacer la conversión aquí dentro de la función? ¿Sería eso mejor que construir la lista añadiendo repetidamente? – dreeves

+0

Dejaría que el usuario de la función convierta el generador en una lista con la función 'list'. Si quieres una función que devuelve directamente una lista, puedes hacer una función auxiliar 'reducelist_helper (f, lst, x = 0): lista de retorno (reducelist (f, lst, x))' – halex

Cuestiones relacionadas