本站消息

站长简介/公众号


站长简介:逗比程序员,理工宅男,前每日优鲜python全栈开发工程师,利用周末时间开发出本站,欢迎关注我的微信公众号:程序员总部,程序员的家,探索程序员的人生之路!分享IT最新技术,关注行业最新动向,让你永不落伍。了解同行们的工资,生活工作中的酸甜苦辣,谋求程序员的最终出路!

 价值13000svip视频教程,前端大神匠心打造,零基础前端开发工程师视频教程全套,基础+进阶+项目实战,包含课件和源码

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2021-03(417)

2021-04(177)

2021-05(161)

2021-06(101)

2021-07(7)

【极客日常】理解javascript/python中reduce操作的含义

发布于2021-10-05 20:56     阅读(897)     评论(0)     点赞(22)     收藏(4)


在学习javascript和python的过程中,我们通常会接触到mapfilterreduce之类的一等公民高阶函数。理解mapfilter是相对简单的事情,但理解reduce的话还是需要一番推敲。正值十一假期,今天这篇文章就好好讲讲reduce这个东西

我们首先以python为例,看一段reduce程序的操作:

from functools import reduce
from dataclasses import dataclass


@dataclass
class Stats:
    product: int = 1
    sum: int = 0
    num: int = 0
    avg: float = 0.0
    max: int = -1e9
    min: int = 1e9


def reducer(cur_state, cur_element):
    assert isinstance(cur_state, Stats)
    print('processing element %d, current stats: %s' % (cur_element, cur_state))
    cur_state.num += 1
    cur_state.sum += cur_element
    cur_state.product *= cur_element
    cur_state.avg = float(cur_state.sum) / float(cur_state.num)
    if cur_element > cur_state.max:
        cur_state.max = cur_element
    if cur_element < cur_state.min:
        cur_state.min = cur_element
    return cur_state


def main():
    ints = [1, 5, 2, 3, 4]
    reduced_stats = reduce(reducer, ints, Stats())
    print(reduced_stats)


if __name__ == '__main__':
    main()

这段程序里的操作,输入是一组整数,最后输出来的是这组整数的统计数据,比如总和sum、积product、最大最小值等等。实现这个统计操作,就可以用reduce。在functools库中,我们可以看到reduce的定义:

_initial_missing = object()

def reduce(function, sequence, initial=_initial_missing):
    """
    reduce(function, sequence[, initial]) -> value

    Apply a function of two arguments cumulatively to the items of a sequence,
    from left to right, so as to reduce the sequence to a single value.
    For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
    ((((1+2)+3)+4)+5).  If initial is present, it is placed before the items
    of the sequence in the calculation, and serves as a default when the
    sequence is empty.
    """

    it = iter(sequence)

    if initial is _initial_missing:
        try:
            value = next(it)
        except StopIteration:
            raise TypeError("reduce() of empty sequence with no initial value") from None
    else:
        value = initial

    for element in it:
        value = function(value, element)

    return value

try:
    from _functools import reduce
except ImportError:
    pass

这段代码简单易懂,我们可以看到reduce函数需要一个初始值initial,并定义一个会变化的当前值value,然后会在遍历我们定义的sequence序列的过程中,不断用function(叫成reducer更加贴切)依据当前遍历到的元素element来更新当前值value(的内部状态),并在最后返回最终的value

所以很显然,reduce这个函数,针对一个特定的sequence,返回值应当反映这个sequence的某样(些)属性。这便是reduce的意义所在了。

学过javascript的同学,会经常在网上资料看到reduce的翻译叫做归并,个人认为归并这个词已经翻译的非常贴切了,一时间也找不到更好的信达雅的表达。当然如果我们去检索英文百科,甚至还可以了解到更多的信息。

reduce是函数式编程的一个代表。我们检索函数式编程的维基百科,里面可以跳到reduce的百科,我们发现其实会跳到另一个单词的百科,叫做fold

fold以及衍生词汇reduceaccumulateaggregation可以看到,这类操作其实用中文翻译除了叫归并以外,叫累积聚合也不过分(嗯这里又可以看到我们的老朋友mongodb,aggregationaccumulate关键词都上架了),都是代表着一种遍历所有元素值,不断合并计算,得出最终结果的运算操作。fold反过来叫做unfold,对应的也是另一个单词的百科,叫做AnamorphismAnamorphism本意是岩石变性渐变,但在计算机领域,作为和fold相反的运算方式,是一个会不断根据当前值来生成下一个值,从而展开出来一个sequence的生成器generator(所以这种运算通俗的说,就翻译为展开即可,跟unfold也很搭)。我们熟悉的斐波那契数列,就可以用unfold/Anamorphism代表的运算方式生成。初始值为(0,1),根据(0,1)生成下一个数字1,根据(1,1)生成下一个数字2。这样不断展开下去,我们就可以得到特定长度的斐波那契数列了。




所属网站分类: 技术文章 > 博客

作者:代码搬运工

链接:http://www.qianduanheidong.com/blog/article/198115/01f967e8e21132f7fff4/

来源:前端黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

22 0
收藏该文
已收藏

评论内容:(最多支持255个字符)