1. 程式人生 > >python 函式 reduce、filter

python 函式 reduce、filter

reduce

>>> reduce(lambda x,y: x+y,[1,2,3,4,5])
15

請看官仔細觀察,是否能夠看出是如何運算的呢?畫一個圖:

image.png

還記得map是怎麼運算的嗎?忘了?看程式碼:

>>> list1 = [1,2,3,4,5,6,7,8,9]
>>> list2 = [9,8,7,6,5,4,3,2,1]
>>> map(lambda x,y: x+y, list1,list2)
[10, 10, 10, 10, 10, 10, 10, 10, 10]

對比一下,就知道兩個的區別了。原來map是上下運算,reduce是橫著逐個元素進行運算。

權威的解釋來自官網:

reduce(function, iterable[, initializer])

Apply function of two arguments cumulatively to the items of iterable, from left to right, so as to reduce the iterable to a single value. For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates ((((1+2)+3)+4)+5). The left argument, x, is the accumulated value and the right argument, y, is the update value from the iterable. If the optional initializer is present, it is placed before the items of the iterable in the calculation, and serves as a default when the iterable is empty. If initializer is not given and iterable contains only one item, the first item is returned. Roughly equivalent to:

def reduce(function, iterable, initializer=None):
    it = iter(iterable)
    if initializer is None:
        try:
            initializer = next(it)
        except StopIteration:    
            raise TypeError('reduce() of empty sequence with no initial value')    
    accum_value = initializer                                                                   
    for x in it:
        accum_value = function(accum_value, x)    
    return accum_value

如果用我們熟悉的for迴圈來做上面reduce的事情,可以這樣來做:

>>> lst = range(1,6)
>>> lst
[1, 2, 3, 4, 5]
>>> r = 0
>>> for i in range(len(lst)):
...     r += lst[i]
... 
>>> r
15

for普世的,reduce是簡潔的。

為了鍛鍊思維,看這麼一個問題,有兩個list,a = [3,9,8,5,2],b=[1,4,9,2,6],計算:a[0]*b[0]+a[1]*b[1]+…的結果。

>>> a
[3, 9, 8, 5, 2]
>>> b
[1, 4, 9, 2, 6]

>>> zip(a,b)        #複習一下zip,下面的方法中要用到
[(3, 1), (9, 4), (8, 9), (5, 2), (2, 6)]

>>> sum(x*y for x,y in zip(a,b))    #解析後直接求和
133

>>> new_list = [x*y for x,y in zip(a,b)]    #可以看做是上面方法的分佈實施
>>> #這樣解析也可以:new_tuple = (x*y for x,y in zip(a,b))
>>> new_list
[3, 36, 72, 10, 12]
>>> sum(new_list)     #或者:sum(new_tuple)
133

>>> reduce(lambda sum,(x,y): sum+x*y,zip(a,b),0)    #這個方法是在耍酷呢嗎?
133

>>> from operator import add,mul            #耍酷的方法也不止一個
>>> reduce(add,map(mul,a,b))
133

>>> reduce(lambda x,y: x+y, map(lambda x,y: x*y, a,b))  #map,reduce,lambda都齊全了,更酷嗎?
133

filter

filter的中文含義是“過濾器”,在python中,它就是起到了過濾器的作用。首先看官方說明:

filter(function, iterable)

filter() 函式用於過濾序列,過濾掉不符合條件的元素,返回由符合條件元素組成的新列表。

該接收兩個引數,第一個為函式,第二個為序列,序列的每個元素作為引數傳遞給函式進行判,然後返回 True 或 False,最後將返回 True 的元素放到新列表中。

通過下面程式碼體會:

>>> numbers = range(-5,5)
>>> numbers
[-5, -4, -3, -2, -1, 0, 1, 2, 3, 4]

>>> filter(lambda x: x>0, numbers) 
[1, 2, 3, 4]

>>> [x for x in numbers if x>0]     #與上面那句等效
[1, 2, 3, 4]

>>> filter(lambda c: c!='i', 'hiekay')  #能不能對應上面文件說明那句話呢?
'hekay'                                  #“If iterable is a string or a tuple, the result also has that type;”