mis*_*tim 108 python reduce functional-programming list fold
在Haskell中实现类似以下内容的最惯用方法是什么:
foldl (+) 0 [1,2,3,4,5]
--> 15
Run Code Online (Sandbox Code Playgroud)
或者它在Ruby中的等价物:
[1,2,3,4,5].inject(0) {|m,x| m + x}
#> 15
Run Code Online (Sandbox Code Playgroud)
显然,Python提供了reduce
函数,这是fold的实现,完全如上所述,然而,有人告诉我,'pythonic'编程方式是避免使用lambda
术语和高阶函数,在可能的情况下更喜欢列表推导.因此,有没有一种首选的方法来折叠Python中的列表或类似列表的结构,而不是reduce
函数,或者是reduce
实现这一目的的惯用方法?
Fre*_*Foo 109
Pythonic总结数组的方法是sum
.对于其他目的,您可以有时使用的某种组合reduce
和functools
模块,如
def product(xs):
return reduce(operator.mul, xs, 1)
Run Code Online (Sandbox Code Playgroud)
请注意,在Haskell术语中,operator
实际上是一个reduce
.没有特殊的语法来执行折叠,没有内置foldl
,实际上使用foldr
非关联运算符被认为是坏样式.
使用高阶函数是相当pythonic; 它充分利用了Python的原则,即一切都是一个对象,包括函数和类.你是对的,一些Python会员不赞同lambdas,但主要是因为当它们变得复杂时它们往往不具有可读性.
Xav*_*hot 17
开始Python 3.8
,并引入赋值表达式 (PEP 572)(:=
运算符),它提供了命名表达式结果的可能性,我们可以使用列表理解来复制其他语言称为 fold/foldleft/reduce 操作的内容:
给定一个列表、一个归约函数和一个累加器:
items = [1, 2, 3, 4, 5]
f = lambda acc, x: acc * x
accumulator = 1
Run Code Online (Sandbox Code Playgroud)
我们可以折叠items
以f
在为了获得所得accumulation
:
[accumulator := f(accumulator, x) for x in items]
# accumulator = 120
Run Code Online (Sandbox Code Playgroud)
或以浓缩形式:
acc = 1; [acc := acc * x for x in [1, 2, 3, 4, 5]]
# acc = 120
Run Code Online (Sandbox Code Playgroud)
请注意,这实际上也是一个“scanleft”操作,因为列表推导式的结果代表了每一步的累积状态:
acc = 1
scanned = [acc := acc * x for x in [1, 2, 3, 4, 5]]
# scanned = [1, 2, 6, 24, 120]
# acc = 120
Run Code Online (Sandbox Code Playgroud)
cla*_*lay 15
哈斯克尔
foldl (+) 0 [1,2,3,4,5]
蟒蛇
reduce(lambda a,b: a+b, [1,2,3,4,5], 0)
显然,这是一个简单的例子来说明一个观点.在Python中你只会做sum([1,2,3,4,5])
,甚至Haskell纯粹主义者通常也会喜欢sum [1,2,3,4,5]
.
对于没有明显的便利功能的非平凡场景,惯用的pythonic方法是明确地写出for循环并使用可变变量赋值而不是使用reduce
或a fold
.
这根本不是功能风格,但那是"pythonic"方式.Python不是为功能纯粹主义者设计的.了解Python如何支持流控制的异常,以了解非功能性的idiomatic python是如何实现的.
Kyr*_*Kyr 12
在Python 3中,reduce
已删除:发行说明.不过你可以使用functools模块
import operator, functools
def product(xs):
return functools.reduce(operator.mul, xs, 1)
Run Code Online (Sandbox Code Playgroud)
另一方面,文档表达了对for
-loop的偏好,而不是reduce
:
def product(xs):
result = 1
for i in xs:
result *= i
return result
Run Code Online (Sandbox Code Playgroud)
您也可以重新发明轮子:
def fold(f, l, a):
"""
f: the function to apply
l: the list to fold
a: the accumulator, who is also the 'zero' on the first call
"""
return a if(len(l) == 0) else fold(f, l[1:], f(a, l[0]))
print "Sum:", fold(lambda x, y : x+y, [1,2,3,4,5], 0)
print "Any:", fold(lambda x, y : x or y, [False, True, False], False)
print "All:", fold(lambda x, y : x and y, [False, True, False], True)
# Prove that result can be of a different type of the list's elements
print "Count(x==True):",
print fold(lambda x, y : x+1 if(y) else x, [False, True, True], 0)
Run Code Online (Sandbox Code Playgroud)
并不是真的回答这个问题,而是折叠和折叠的一线:
a = [8,3,4]
## Foldl
reduce(lambda x,y: x**y, a)
#68719476736
## Foldr
reduce(lambda x,y: y**x, a[::-1])
#14134776518227074636666380005943348126619871175004951664972849610340958208L
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
82364 次 |
最近记录: |