使用reduce()的有用代码?
这里有没有人有任何有用的代码在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"轻松地对其进行定义。
正如其他人提到的那样,可读性确实是一个问题。但是,我们可能会争辩说,人们发现减少"清晰"效果的唯一原因仅仅是因为它不是许多人知道和/或者使用的功能。
回答
除了+和*外,我为它找到的其他用途还有和和或者,但是现在我们用any
和all
来代替这些情况。
foldl
和foldr
确实出现在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交集