使用reduce()的有用代码?

时间:2020-03-05 18:40:41  来源:igfitidea点击:

这里有没有人有任何有用的代码在python中使用reduce()函数?除了示例中常见的+和*以外,是否还有其他代码?

通过GvR引用Python 3000中的reduce()的命运

解决方案

回答

不知道这是我们要追求的,但是我们可以在Google上搜索源代码。

按照链接在Google Code搜索上搜索" function:reduce()lang:python"

乍看之下,以下项目使用reduce()

  • MoinMoin
  • 佐佩
  • 数字
  • 科学Python

等),但由于它们是巨大的项目,因此这些不足为奇。

reduce的功能可以使用函数递归来完成,我猜Guido认为它更明确。

更新:

由于Google的代码搜索已于2012年1月15日停产,因此除了恢复常规的Google搜索外,还有一个名为"代码片段集合"的东西看起来很有希望。在这个(封闭的)问题" Google代码搜索的替换?"的答案中提到了许多其他资源。

更新2(2017年5月29日):

Nullegesearchengine是Python示例(在开放源代码中)的一个很好的来源。

回答

我有一个旧的pipegrep Python实现,该实现使用reduce和glob模块来构建要处理的文件列表:

files = []
files.extend(reduce(lambda x, y: x + y, map(glob.glob, args)))

当时我觉得很方便,但实际上没有必要,因为类似的东西一样好,而且可读性更高

files = []
for f in args:
    files.extend(glob.glob(f))

回答

@Blair Conrad:我们也可以使用sum来实现glob / reduce,如下所示:

files = sum([glob.glob(f) for f in args], [])

它比两个示例中的任何一个都不那么冗长,完全是Python风格的,并且仍然只是一行代码。

因此,为了回答最初的问题,我个人尝试避免使用reduce,因为它从来没有真正需要过,而且我发现它比其他方法不太清楚。但是,有些人习惯于减少并开始喜欢它来列出理解(特别是Haskell程序员)。但是,如果我们还没有考虑过reduce的问题,那么我们可能不必担心使用它。

回答

重复我的代码后,看来我使用过的reduce唯一的作用就是计算阶乘:

reduce(operator.mul, xrange(1, x+1) or (1,))

回答

我在代码中发现的" reduce"用法涉及一种情况,即我具有一些用于逻辑表达式的类结构,因此需要将这些表达式对象的列表转换为表达式的并集。我已经有一个函数make_and来给定两个表达式来创建一个合取,所以我写了reduce(make_and,l)。 (我知道列表不是空的;否则它将是类似reduce(make_and,l,make_true)的东西。)

这正是(某些)函数式程序员喜欢" reduce"(或者通常称为折叠函数)的原因。通常已经有很多二进制函数,例如+,*,min,max,串联,在我的情况下是make_and和make_or。拥有一个" reduce"使得将这些操作提升到列表(或者一般来说是折叠功能的树或者我们所得到的东西)变得微不足道。

当然,如果经常使用某些实例化(例如" sum"),那么我们就不想继续编写" reduce"。但是,除了使用一些for循环定义" sum"外,我们也可以使用" reduce"轻松地对其进行定义。

正如其他人提到的那样,可读性确实是一个问题。但是,我们可能会争辩说,人们发现减少"清晰"效果的唯一原因仅仅是因为它不是许多人知道和/或者使用的功能。

回答

除了+和*外,我为它找到的其他用途还有和和或者,但是现在我们用anyall来代替这些情况。

foldlfol​​dr确实出现在Scheme中...

这是一些可爱的用法:

整理清单

目标:将[[[1、2、3],[4、5],[6、7、8]]`变成[[1、2、3、4、5、6、7、8]。

reduce(list.__add__, [[1, 2, 3], [4, 5], [6, 7, 8]], [])

数字列表到一个数字

目标:将" [1、2、3、4、5、6、7、8]"变成" 12345678"。

丑陋,缓慢的方式:

int("".join(map(str, [1,2,3,4,5,6,7,8])))

漂亮的"减少"方式:

reduce(lambda a,d: 10*a+d, [1,2,3,4,5,6,7,8], 0)

回答

reduce()可用于查找3个或者更多数字的最小公倍数:

#!/usr/bin/env python
from fractions import gcd
from functools import reduce

def lcm(*args):
    return reduce(lambda a,b: a * b // gcd(a, b), args)

例子:

>>> lcm(100, 23, 98)
112700
>>> lcm(*range(1, 20))
232792560

回答

reduce()可用于解析点名(其中eval()太不安全,无法使用):

>>> import __main__
>>> reduce(getattr, "os.path.abspath".split('.'), __main__)
<function abspath at 0x009AB530>

回答

我正在为一种语言编写一个compose函数,因此我将reduce与我的apply运算符一起构造了复合函数。

简而言之,compose将一系列函数组合成一个函数。如果我有一个分阶段应用的复杂操作,那么我想像这样将它们放在一起:

complexop = compose(stage4, stage3, stage2, stage1)

这样,我便可以将其应用到这样的表达式中:

complexop(expression)

我希望它等同于:

stage4(stage3(stage2(stage1(expression))))

现在,要构建内部对象,我希望它说:

Lambda([Symbol('x')], Apply(stage4, Apply(stage3, Apply(stage2, Apply(stage1, Symbol('x'))))))

(Lambda类构建用户定义的函数,Apply构建函数应用程序。)

现在,不幸的是,reduce折叠的方向错误,所以我大致使用了:

reduce(lambda x,y: Apply(y, x), reversed(args + [Symbol('x')]))

要弄清楚reduce产生了什么,请在REPL中尝试以下方法:

reduce(lambda x, y: (x, y), range(1, 11))
reduce(lambda x, y: (y, x), reversed(range(1, 11)))

回答

找到N个给定列表的交集:

input_list = [[1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [3, 4, 5, 6, 7]]

result = reduce(set.intersection, map(set, input_list))

返回:

result = set([3, 4, 5])

通过:两个列表的Python交集