Python 高阶函数 -- map/reduce

这个内容我是参考廖雪峰的博客,摘抄其中一些内容而来的,附带解决他最后的问题代码。

  1.  这是我在C/C++中未曾见过的语法(可能是我学艺未精),理解它确实花了十来二十分钟。它提供了一条google的论文链接:“MapReduce: Simplified Data Processing on Large Clusters",据说是一篇很牛逼的文章。当我理解了这个概念后,觉得确实很方便。
  2. 先看map。map()函数接收两个参数,一个是函数,一个是Iterablemap将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。

    举例说明,比如我们有一个函数f(x)=x2,要把这个函数作用在一个list [1, 2, 3, 4, 5, 6, 7, 8, 9]上,就可以用map()实现如下:

                f(x) = x * x
    
                      │
                      │
      ┌────────────--------───┐
      │   │   │   │   │   │   │   │   │
      ▼   ▼   ▼   ▼   ▼   ▼   ▼   ▼   ▼
    
    [ 1    2    3    4    5    6    7    8    9 ]
    
      │   │   │   │   │   │   │   │   │
      │   │   │   │   │   │   │   │   │
      ▼   ▼   ▼   ▼   ▼   ▼   ▼   ▼   ▼
    
    [ 1    4    9   16    25   36   49   64   81 ]
    

    现在,我们用Python代码实现:

    1 >>> def f(x):
    2 ...     return x * x
    3 ...
    4 >>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
    5 >>> list(r)
    6 [1, 4, 9, 16, 25, 36, 49, 64, 81]

    map()传入的第一个参数是f,即函数对象本身。由于结果r是一个IteratorIterator是惰性序列,因此通过list()函数让它把整个序列都计算出来并返回一个list。

  3. 再看reduce的用法。reduce把一个函数作用在一个序列[x1, x2, x3, ...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:
    reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

    比方说对一个序列求和,就可以用reduce实现:
    >>> from functools import reduce
    >>> def add(x, y):
    ...     return x + y
    ...
    >>> reduce(add, [1, 3, 5, 7, 9])
    25

    这个例子本身没多大用处,但是,如果考虑到字符串str也是一个序列,对上面的例子稍加改动,配合map(),我们就可以写出把str转换为int的函数:

    >>> from functools import reduce
    >>> def fn(x, y):
    ...     return x * 10 + y
    ...
    >>> def char2num(s):
    ...     digits = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
    ...     return digits[s]
    ...
    >>> reduce(fn, map(char2num, '13579'))
    13579
  4. 练习

    1. 利用map()函数,把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字。输入:['adam', 'LISA', 'barT'],输出:['Adam', 'Lisa', 'Bart']
      #-*- coding: utf-8 -*-
      def normalize(name):
          return name.capitalize()
      
      # 测试:
      L1 = ['adam', 'LISA', 'barT']
      L2 = list(map(normalize, L1))
      print(L2)
    2. Python提供的sum()函数可以接受一个list并求和,请编写一个prod()函数,可以接受一个list并利用reduce()求积
      # -*- coding: utf-8 -*-
      from functools import reduce
      
      def prod(L):
          def fn(x,y):
              return x*y
          return reduce(fn,L)
      
      print('3 * 5 * 7 * 9 =', prod([3, 5, 7, 9]))
      if prod([3, 5, 7, 9]) == 945:
          print('测试成功!')
      else:
          print('测试失败!')
    3. 利用mapreduce编写一个str2float函数,把字符串'123.456'转换成浮点数123.456
      # -*- coding: utf-8 -*-
      from functools import reduce
      
      def str2float(s):
          DIGITS = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
          pos = len(s)-s.index(".")-1 #寻找小数位
      
          def char2num(my_str):
              if(my_str != "."):
                  return DIGITS[my_str]
      
          def fn(x,y):
              if y==None:
                  return x
              else:
                  return 10*x+y
          return reduce(fn,map(char2num,s))/(10**pos)
      
      print('str2float(\'123.456\') =', str2float('123.456'))
      if abs(str2float('123.456') - 123.456) < 0.00001:
          print('测试成功!')
      else:
          print('测试失败!')

猜你喜欢

转载自www.cnblogs.com/ChrisK/p/9461362.html