Python filter(), map(), reduce() and lambda

Keywords: Lambda Python Java

1.lambda definition

python allows you to create anonymous functions with lambda keywords. Parameters are optional and, if used, are usually part of the expression. The grammar of the lower anonymous function:

lambda [arg1[, arg2, ... argN]]: expression

def true(): return True
#Amount to
lambda :True

In the example above, we simply created a function (object) with lambda, but neither saved it anywhere nor invoked it. The reference count of this function object is set to True when the function is created, but since no reference is saved, the count goes back to zero and is garbage collected. To preserve this object, we save it in a variable that can be called at any time in the future:

>>> true = lambda :True
>>> true() True

Several examples:

>>> a = lambda x, y=2: x + y
>>> a(3)
5
>>> a(3,5)
8
>>> a(0)
2
>>> a(0,9)
9
>>>
>>> b = lambda *z: z //Variable length parameter
>>> b(23, 'zyx')
(23, 'zyx')
>>> b(42)
(42,)

2. Built-in functions filter(), map(), reduce() are used in conjunction with lambda

  • filter(func, seq): Call a Boolean function func to iterate over the elements in each seq; return a sequence of elements that make func return value ture.
  • map(func, seq1[,seq2... ]: Function func acts on each element of a given sequence (s) and provides a return value with a list; if func is None, func acts as an identity function, returning a list of n tuples containing the set of elements in each sequence.
  • reduce(func, seq[, init]): The binary function acts on the elements of the seq sequence, each time carrying a pair (the previous result and the next sequence element), continuously applying the existing result and the next value to the subsequent results obtained, and finally reducing our sequence to a single return value; if the initial value init is given, the first comparison will be init and the first one. Sequence elements are not the first two elements of a sequence.

If we want to write filter() in pure python, it might be like this:

def filter(bool_func, seq):
    filtered_seq = []
    for eachItem in seq:
        if bool_func(eachItem):
            filtered_seq.append(eachItem)
    return filtered_seq

Here's a script that uses filer() to get a short list of arbitrary odd numbers. The script generates a large set of random numbers, then filters out all even numbers, leaving us with a required data set. When you start writing this example, oddnogen.py looks like this:

from random import randint

def odd(n):
    return n % 2

allNums = []
for eachNum in range(9):
    allNums.append(randint(1, 99))

print filter(odd, allNums)

Replace with a lambda expression:

from random import randint

allNums = []
for eachNum in range(9):
    allNums.append(randint(1, 99))

print filter(lambda n: n%2, allNums)

Replace with list resolution:

from random import randint

allNums = []
for eachNum in range(9):
    allNums.append(randint(1, 99))

print [n for n in allNums if n%2]

To further simplify our code, we put our final list together by integrating additional list parsing:

from random import randint as ri
print [n for n in [ri(1,99) for i in range(9)] if n%2]

If we were to write how this simple form of map() works in python, it might have the following code:

def map(func, seq):
    mapped_seq = []
    for eachItem in seq:
        mapped_seq.append(func(eachItem))
    return mapped_seq

List a few short lambda functions to show how to use map() to process actual data (list parsing has the same function):

>>> map((lambda x: x+2), [0, 1, 2, 3, 4, 5])
[2, 3, 4, 5, 6, 7]
>>> map(lambda x: x**2, range(6))
[0, 1, 4, 9, 16, 25]
>>> [x+2 for x in range(6)]
[2, 3, 4, 5, 6, 7]
>>>[x**2 for x in range(6)]
[0, 1, 4, 9, 16, 25]

Here is an example of using map() with multiple sequences:

>>> map(lambda x, y: x + y, [1,3,5], [2,4,6])
[3, 7, 11]
>>> map(lambda x, y: (x+y, x-y), [1,3,5], [2,4,6])
[(3, -1), (7, -1), (11, -1)]
>>> map(None, [1,3,5], [2,4,6])
[(1, 2), (3, 4), (5, 6)]

The last example above uses map() and a function object for None to merge irrelevant sequences. This idea was common in Python 2.0 before a new built-in function, zip, was added. Zip does this:

>>> zip([1,3,5], [2,4,6])
[(1, 2), (3, 4), (5, 6)]

If we want to try reducing () with pure python, it might be like this:

def reduce(bin_func, seq, init=None):
    lseq = list(seq) # convert to list
    if init is None: # initializer?
        res = lseq.pop(0) # no
    else:
        res = init # yes
    for item in lseq: # reduce sequence
        res = bin_func(res, item) # apply function
    return res # return result

Here is an example:

>>> def mySum(x,y): return x+y
>>> for eachNum in allNums:
... total = mySum(total, eachNum)
...
>>> print 'the total is:', total
the total is: 10

With lambda and reduce(), we can do the same thing in one line of code.

>>> print 'the total is:', reduce((lambda x,y: x+y), range(5))
the total is: 10

Given the input above, the reduce() function performs the following arithmetic operations.

((((0 + 1) + 2) + 3) + 4) => 10

3. Sorting code using lambda

# -*- coding: utf-8 -*-

a = 'awk#39'
b = 'sed#1'
c = 'java#21'
d = 'python#100'

data = [a, b, c, d]

print data  # ['awk#39', 'sed#1', 'java#21', 'python#100']
data.sort(key=lambda x: int(x.split('#')[1]))
print data  # ['sed#1', 'java#21', 'awk#39', 'python#100']

Posted by gasper000 on Sat, 15 Dec 2018 14:18:03 -0800