2012-09-02 3 views
5

Sie kennen die handliche reduce Funktion in Python. Zum Beispiel könnten Sie es verwenden, um eine Liste zusammenzufassen, wie so (so tun, als es nicht die eingebaute in sum ist):Reduplist in Python: wie reduzieren, aber die Liste der Zwischenergebnisse geben

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

, die zurückgibt (((0 + 1) 2) 3) + 4 = 10.

Was nun, wenn ich eine Liste der Zwischensummen wollte? In diesem Fall [1,3,6,10].

Hier ist eine hässliche Lösung. Gibt es etwas Pythonsches?

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

FYI, zumindest in Haskell wird dies als * Scan * bekannt. Reduce wird in der Welt der funktionalen Programmierung auch als (eine spezifische Art von) * falten * bezeichnet. – delnan

+0

Danke delnan, yeah, ich kenne das als FoldList von Mathematica. Mathematica hat eine akkumulierende Version vieler dieser funktionalen Programmierfunktionen, die durch Anhängen von "List" bezeichnet sind. Ich sehe aus der Antwort unten, dass in Python 3, was ich Reduplist aufrufen, jetzt als accumulate() verfügbar ist. – dreeves

Antwort

8

Mein Favorit, wenn Sie neu genug:

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 auch ein Funktionsargument akzeptiert [noch neuere, though-- 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, schön! Obwohl das für mich sowohl zu neu ist (ich bin in Python 2) als auch zu spezifisch (das ist nur zum Summieren, nicht die allgemeine Reduktionsliste, nach der ich suche). EDIT: Ah, es * ist * allgemein genug, mit diesem optionalen Argument; Vielen Dank! – dreeves

8

Wenn Sie Machen Sie Ihre Lösung zu einem Generator, der kürzer ist und besser dem funktionalen Programmierstil entspricht. Ich würde auch einen Standardwert von 0 für x hinzufügen:

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

, die definitiv mehr ist pythonic.

+0

Danke! Was wäre, wenn Sie eine aktuelle Liste zurückgeben müssten? Können wir die Konvertierung hier innerhalb der Funktion vornehmen? Wäre das immer noch besser, als die Liste durch wiederholtes Anhängen zu erstellen? – dreeves

+0

Ich würde es dem Benutzer der Funktion überlassen, den Generator in eine Liste mit 'List'-Funktion umzuwandeln. Wenn Sie eine Funktion wünschen, die eine Liste direkt zurückgibt, können Sie eine Hilfsfunktion machen 'reduplist_helper (f, lst, x = 0): Liste zurückgeben (reduplist (f, lst, x))' – halex

Verwandte Themen