cnu*_*cnu 120 python functional-programming
这里有没有人有任何有用的代码在python中使用reduce()函数?除了我们在示例中看到的通常的+和*之外,还有其他代码吗?
通过GvR 参考Python 3000中的reduce()命运
Cla*_*diu 64
除了+和*之外,我发现的其他用途与和和或,但现在我们已经any和all更换这些情况.
foldl并foldr在计划中提出了很多......
这是一些可爱的用法:
压平列表
目标:[[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]], [])
Run Code Online (Sandbox Code Playgroud)
数字的数字列表
目标:[1, 2, 3, 4, 5, 6, 7, 8]变成12345678.
丑陋,缓慢的方式:
int("".join(map(str, [1,2,3,4,5,6,7,8])))
Run Code Online (Sandbox Code Playgroud)
漂亮的reduce方式:
reduce(lambda a,d: 10*a+d, [1,2,3,4,5,6,7,8], 0)
Run Code Online (Sandbox Code Playgroud)
jfs*_*jfs 50
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)
Run Code Online (Sandbox Code Playgroud)
例:
>>> lcm(100, 23, 98)
112700
>>> lcm(*range(1, 20))
232792560
Run Code Online (Sandbox Code Playgroud)
jfs*_*jfs 38
reduce()可用于解析虚线名称(eval()使用起来太不安全):
>>> import __main__
>>> reduce(getattr, "os.path.abspath".split('.'), __main__)
<function abspath at 0x009AB530>
Run Code Online (Sandbox Code Playgroud)
sso*_*ler 23
找到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))
Run Code Online (Sandbox Code Playgroud)
收益:
result = set([3, 4, 5])
Run Code Online (Sandbox Code Playgroud)
via:Python - 两个列表的交集
小智 12
我认为减少是一个愚蠢的命令.因此:
reduce(lambda hold,next:hold+chr(((ord(next.upper())-65)+13)%26+65),'znlorabggbbhfrshy','')
Run Code Online (Sandbox Code Playgroud)
mwe*_*den 11
reduce我在代码中找到的用法涉及到我有一些逻辑表达式的类结构的情况,我需要将这些表达式对象的列表转换为表达式的连接.我已经有了一个函数make_and来创建一个给出两个表达式的连接,所以我写了reduce(make_and,l).(我知道列表不是空的;否则它就像是reduce(make_and,l,make_true).)
这正是(某些)函数式程序员喜欢reduce(或折叠函数,因为这些函数通常被称为)的原因.经常有像已经有很多二元函数+,*,min,max,级联和,在我的情况,make_and和make_or.有一个reduce使得将这些操作提升到列表(或树或任何你得到的,一般的折叠函数)是微不足道的.
当然,如果sum经常使用某些实例(例如),那么你不想继续写作reduce.但是,不是sum使用一些for循环定义,而是可以轻松地定义它reduce.
其他人提到的可读性确实是一个问题.然而,你可以争辩说,只有人们发现reduce不那么"清晰"的原因是因为它不是许多人知道和/或使用的功能.
您可以替换value = json_obj['a']['b']['c']['d']['e']为:
value = reduce(dict.__getitem__, 'abcde', json_obj)
Run Code Online (Sandbox Code Playgroud)
如果您已将路径a/b/c/..作为列表.例如,使用列表中的项目更改嵌套dicts的dict中的值.
功能组合:如果您已经有一系列要连续申请的功能,例如:
color = lambda x: x.replace('brown', 'blue')
speed = lambda x: x.replace('quick', 'slow')
work = lambda x: x.replace('lazy', 'industrious')
fs = [str.lower, color, speed, work, str.title]
Run Code Online (Sandbox Code Playgroud)
然后你可以连续应用它们:
>>> call = lambda s, func: func(s)
>>> s = "The Quick Brown Fox Jumps Over the Lazy Dog"
>>> reduce(call, fs, s)
'The Slow Blue Fox Jumps Over The Industrious Dog'
Run Code Online (Sandbox Code Playgroud)
在这种情况下,方法链可能更具可读性.但有时这是不可能的,这种组合可能比f1(f2(f3(f4(x))))一种语法更具可读性和可维护性.
@Blair Conrad:您还可以使用sum实现glob/reduce,如下所示:
files = sum([glob.glob(f) for f in args], [])
Run Code Online (Sandbox Code Playgroud)
这比你的两个例子中的任何一个都要简洁,完全是Pythonic,并且仍然只有一行代码.
因此,为了回答原始问题,我个人试图避免使用reduce,因为它从来没有真正必要,我发现它不如其他方法清晰.然而,有些人习惯于减少并更喜欢列出理解(尤其是Haskell程序员).但是,如果你还没有考虑减少问题,你可能不必担心使用它.
reduce 可用于支持链式属性查找:
reduce(getattr, ('request', 'user', 'email'), self)
Run Code Online (Sandbox Code Playgroud)
当然,这相当于
self.request.user.email
Run Code Online (Sandbox Code Playgroud)
但是当您的代码需要接受任意属性列表时,它很有用.
(处理Django模型时,任意长度的链式属性都很常见.)
reduce当您需要查找类似对象序列的并集或交集时,此功能非常有用set。
>>> reduce(operator.or_, ({1}, {1, 2}, {1, 3})) # union
{1, 2, 3}
>>> reduce(operator.and_, ({1}, {1, 2}, {1, 3})) # intersection
{1}
Run Code Online (Sandbox Code Playgroud)
(除了实际的sets 之外,其中的一个例子是Django 的 Q 对象。)
另一方面,如果您正在处理bools,则应该使用anyand all:
>>> any((True, False, True))
True
Run Code Online (Sandbox Code Playgroud)
不确定这是否是您想要的,但您可以在 Google 上搜索源代码。
点击链接在 Google Code 搜索中搜索“function:reduce() lang:python”
乍一看以下项目使用reduce()
等等,但这些并不奇怪,因为它们是巨大的项目。
reduce 的功能可以使用函数递归来完成,我猜 Guido 认为这更明确。
更新:
由于 Google 的代码搜索已于 2012 年 1 月 15 日停止,除了恢复到常规 Google 搜索之外,还有一个名为“代码片段集合”的东西看起来很有前途。这个(已关闭)问题的答案中提到了许多其他资源替代 Google 代码搜索?。
更新 2(2017 年 5 月 29 日):
Nullege 搜索引擎是 Python 示例(开源代码)的一个很好的来源。
| 归档时间: |
|
| 查看次数: |
80087 次 |
| 最近记录: |