python中的map, filter, and reduce

来源:互联网 发布:阮一峰 javascript 编辑:程序博客网 时间:2024/05/12 12:21
map, filter, and reduce

Python provides several functions which enable a functional approach to programming. These functions are all convenience features in that they can be written in Python fairly easily.




bogotobogo.com site search:


Functional programming is all aboutexpressions. We may say that the Functional programming is anexpression oriented programming.

Expression oriented functions of Python provides are:

  • map(aFunction, aSequence)
  • filter(aFunction, aSequence)
  • reduce(aFunction, aSequence)
  • lambda
  • list comprehension




map

One of the common things we do with list and other sequences is applying an operation to each item and collect the result. For example, updating all the items in a list can be done easily with afor loop:

>>> items = [1, 2, 3, 4, 5]>>> squared = []>>> for x in items:squared.append(x ** 2)>>> squared[1, 4, 9, 16, 25]>>> 

Since this is such a common operation, actually, we have a built-in feature that does most of the work for us. Themap(aFunction, aSequence) function applies a passed-in function to each item in an iterable object and returns a list containing all the function call results.

>>> items = [1, 2, 3, 4, 5]>>> >>> def sqr(x): return x ** 2>>> list(map(sqr, items))[1, 4, 9, 16, 25]>>> 

We passed in a user-defined function applied to each item in the list.map callssqr on each list item and collects all the return values into a new list.



Because map expects a function to be passed in, it also happens to be one of the places wherelambda routinely appears:

>>> list(map((lambda x: x **2), items))[1, 4, 9, 16, 25]>>> 

In the short example above, the lambda function squares each item in the items list.




As shown earlier, map is defined like this:

map(aFunction, aSequence)

While we still use lamda as aaFunction, we can have alist of functions asaSequence:

def square(x):        return (x**2)def cube(x):        return (x**3)funcs = [square, cube]for r in range(5):    value = map(lambda x: x(r), funcs)    print value

Output:

[0, 0][1, 1][4, 8][9, 27][16, 64]



Because using map is equivalent tofor loops, with an extra code we can always write a general mapping utility:

>>> def mymap(aFunc, aSeq):result = []for x in aSeq: result.append(aFunc(x))return result>>> list(map(sqr, [1, 2, 3]))[1, 4, 9]>>> mymap(sqr, [1, 2, 3])[1, 4, 9]>>> 

Since it's a built-in, map is always available and always works the same way. It also has some performance benefit because it is usually faster than a manually codedfor loop. On top of those, map can be used in more advance way. For example, given multiple sequence arguments, it sends items taken form sequences in parallel as distinct arguments to the function:

>>> pow(3,5)243>>> pow(2,10)1024>>> pow(3,11)177147>>> pow(4,12)16777216>>> >>> list(map(pow,[2, 3, 4], [10, 11, 12]))[1024, 177147, 16777216]>>> 

As in the example above, with multiple sequences,map() expects an N-argument function for N sequences. In the example,pow function takes two arguments on each call.

The map call is similar to thelist comprehension expression. Butmap applies afunction call to each item instead of anarbitrary expression. Because of this limitation, it is somewhat less general tool. In some cases, however,map may be faster to run than a list comprehension such as when mapping a built-in function. Andmap requires less coding.

If function is None, the identity function is assumed; if there are multiple arguments,map() returns a list consisting oftuples containing the corresponding items from all iterables (a kind of transpose operation). The iterable arguments may be a sequence or any iterable object; the result is always a list:

>>> m = [1,2,3]>>> n = [1,4,9]>>> new_tuple = map(None, m, n)>>> new_tuple[(1, 1), (2, 4), (3, 9)]




bogotobogo.com site search:



filter and reduce

As the name suggests filter extracts each element in the sequence for which the function returnsTrue. Thereduce function is a little less obvious in its intent. This function reduces a list to a single value by combining elements via a supplied function. Themap function is the simplest one among Python built-ins used forfunctional programming.

These tools apply functions to sequences and other iterables. Thefilter filters out items based on a test function which is afilter and apply functions to pairs of item and running result which isreduce.

Because they return iterables, range andfilter both requirelist calls to display all their results in Python 3.0.

As an example, the following filter call picks out items in a sequence that are less than zero:

>>> list(range(-5,5))[-5, -4, -3, -2, -1, 0, 1, 2, 3, 4]>>>>>> list( filter((lambda x: x < 0), range(-5,5)))[-5, -4, -3, -2, -1]>>> 

Items in the sequence or iterable for which the function returns a true, the result are added to the result list. Likemap, this function is roughly equivalent to afor loop, but it is built-in and fast:

>>> >>> result = []>>> for x in range(-5, 5):if x < 0:result.append(x)>>> result[-5, -4, -3, -2, -1]>>> 

The reduce is in thefunctools in Python 3.0. It is more complex. It accepts an iterator to process, but it's not an iterator itself. It returns a single result:

>>> >>> from functools import reduce>>> reduce( (lambda x, y: x * y), [1, 2, 3, 4] )24>>> reduce( (lambda x, y: x / y), [1, 2, 3, 4] )0.041666666666666664>>> 

At each step, reduce passes the current product or division, along with the next item from the list, to the passed-inlambda function. By default, the first item in the sequence initialized the starting value.

Here's the for loop version of the first of these calls, with the multiplication hardcoded inside the loop:

>>> L = [1, 2, 3, 4]>>> result = L[0]>>> for x in L[1:]:result = result * x>>> result24>>> 

Let's make our own version of reduce.

>>> def myreduce(fnc, seq):tally = seq[0]for next in seq[1:]:tally = fnc(tally, next)return tally>>> myreduce( (lambda x, y: x * y), [1, 2, 3, 4])24>>> myreduce( (lambda x, y: x / y), [1, 2, 3, 4])0.041666666666666664>>> 

We can concatenate a list of strings to make a sentence. Using theDijkstra's famous quote on bug:

import functools>>> L = ['Testing ', 'shows ', 'the ', 'presence', ', ','not ', 'the ', 'absence ', 'of ', 'bugs']>>> functools.reduce( (lambda x,y:x+y), L)'Testing shows the presence, not the absence of bugs'>>> 

We can get the same result by using join :

>>> ''.join(L)'Testing shows the presence, not the absence of bugs'

We can also use operator to produce the same result:

>>> import functools, operator>>> functools.reduce(operator.add, L)'Testing shows the presence, not the absence of bugs'>>> 

The built-in reduce also allows an optional third argument placed before the items in the sequence to serve as a default result when the sequence is empty.

0 0
原创粉丝点击