2012-09-02 15 views
5

Python'da kullanışlı reduce işlevini biliyorsunuz. döndürürreducelist: azaltma ama ara sonuç listesini verme gibi

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

(((0 + 1) +2) +3) +: Örneğin, (built-in sum yokmuş gibi davranılırsa) şöyle bir liste özetlemek için kullanabilirsiniz 4 = 10.

Şimdi ara meblağların bir listesini nasıl istersem? Bu durumda, [1,3,6,10].

İşte çirkin bir çözüm. Daha pythonic bir şey var mı?

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

FYI, en azından Haskell'de bu, * scan * olarak bilinir. Azaltmak, fonksiyonel programlama dünyasında da (belirli bir tür) * katlama * olarak bilinir. – delnan

+0

Teşekkürler delnan, bunu Mathematica'dan FoldList olarak biliyorum. Mathematica, "Liste" eklenmesiyle belirtilen bu fonksiyonel programlama fonksiyonlarının çoğunun biriken bir versiyonuna sahiptir. Python 3'te reducelist dediğim şeyin şu anda birikim() olarak kullanılabileceğine dair cevabı görüyorum. – dreeves

cevap

8

Benim favori, yeterince son iseniz:

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 da bir işlev bağımsız değişken kabul [hatta daha yeni rağmen-- 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, güzel! Her ne kadar benim için bu ikisi de çok yeni (Python 2'deyim) ve çok spesifik (bu sadece özetlemek için değil, genel reducelist şeyi arıyorum). DÜZENLEME: Ah, bu * isteğe bağlı argüman ile * yeterince geneldir; Teşekkürler! – dreeves

8

Eğer Çözümünüzü bir jeneratöre daha kısaltın ve fonksiyonel programlama tarzına daha iyi uyun. Ben de x için 0 bir varsayılan değeri eklersiniz:

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

kesinlikle daha pythonic olduğunu That.

+0

Teşekkürler! Ya gerçek bir listeyi geri göndermeniz gerekirse? Buradaki işlevi burada yapabilir miyiz? Tekrar tekrar ekleyerek listeyi oluşturmaktan daha iyi olur mu? – dreeves

+0

Bu işlevi, işlevi "list" işleviyle bir listeye dönüştürmek için işlevin kullanıcısına bırakırım. Doğrudan bir liste döndüren bir işlev istiyorsanız, bir yardımcı işlev yapabilirdiniz 'reducelist_helper (f, lst, x = 0): return listesi (reducelist (f, lst, x))' – halex