2012-09-02 20 views
5

Bạn biết hàm reduce tiện dụng bằng Python. Ví dụ, bạn có thể sử dụng nó để tổng hợp một danh sách như vậy (giả vờ không có built-in sum):reducelist trong Python: như giảm nhưng đưa ra danh sách các kết quả trung gian

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

trả về (((0 + 1) 2) 3) + 4 = 10.

Bây giờ nếu tôi muốn danh sách các khoản tiền trung gian thì sao? Trong trường hợp này, [1,3,6,10].

Đây là giải pháp xấu. Có cái gì đó thêm pythonic?

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

FYI, ít nhất trong Haskell, điều này được gọi là * scan *. Giảm còn được gọi là (một loại cụ thể) * gấp * trong thế giới lập trình chức năng. – delnan

+0

Cảm ơn delnan, yeah, tôi biết điều này là FoldList từ Mathematica. Mathematica có một phiên bản tích lũy của rất nhiều chức năng lập trình chức năng này, được biểu thị bằng cách thêm vào "Danh sách". Tôi thấy từ câu trả lời dưới đây rằng trong Python 3 cái mà tôi gọi là reducelist bây giờ đã có sẵn như là tích lũy(). – dreeves

Trả lời

8

ưa thích của tôi, nếu bạn đang ở gần đây đủ:

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 cũng chấp nhận một chức năng lập luận [thậm chí gần đây, 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, đẹp quá! Mặc dù đối với tôi, đây là cả hai quá gần đây (tôi đang ở Python 2) và quá cụ thể (đây chỉ là để tổng hợp, không phải là điều giảm tốc nói chung tôi đang tìm kiếm). EDIT: Ah, nó * là * đủ chung, với đối số tùy chọn đó; cảm ơn! – dreeves

8

Nếu bạn làm cho giải pháp của bạn cho một máy phát điện ngắn hơn và nó tốt hơn tuân theo phong cách lập trình chức năng. Tôi sẽ thêm một giá trị mặc định 0 cho x quá:

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

Đó chắc chắn là nhiều pythonic.

+0

Cảm ơn! Điều gì xảy ra nếu bạn cần trả lại một danh sách thực tế? Chúng ta có thể thực hiện chuyển đổi ở đây trong hàm không? Điều đó vẫn còn tốt hơn việc xây dựng danh sách bằng cách liên tục thêm vào? – dreeves

+0

Tôi sẽ để nó cho người dùng của hàm để chuyển đổi trình tạo thành danh sách có chức năng 'list'. Nếu bạn muốn một hàm trả về trực tiếp một danh sách, bạn có thể tạo một hàm trợ giúp 'reducelist_helper (f, lst, x = 0): danh sách trả về (reducelist (f, lst, x))' – halex

Các vấn đề liên quan