我必须使用函数式编程来实现以下函数,其中包含0到9之间的数字列表。目标是找到列表中具有最大乘积的五个连续元素。该函数应使用 max 函数返回最大产品索引的元组和最大产品的值 。
我可以在没有函数式编程的情况下轻松实现它,但是在没有任何循环的情况下实现它很困难。 到目前为止,这是我的方法,但我坚持的部分是如何遍历数组以找到没有循环的连续五个数字。我正在尝试使用map来做到这一点,但我不认为这是正确的。是否有可能以任何方式合并枚举?任何帮助表示赞赏。
def find_products(L):
val = map(lambda a: reduce(lambda x,y: x*y, L),L)
print (val)
答案 0 :(得分:7)
from functools import reduce #only for python3, python2 doesn't need import
def find_products(L):
if len(L)==0:
return 0
if len(L) <= 5:
return reduce( lambda x,y:x*y, L)
pdts = ( reduce(lambda a,b:a*b,L[pos:pos+5]) for pos in range(len(L)-4)) # or pdts = map(lambda pos: reduce(lambda a,b:a*b,L[pos:pos+5],0),range(len(L)-4))
mx = reduce(lambda x,y: x if x>y else y, pdts)
return mx
pdts
包含所有可能的5个元组产品,然后使用reduce
模仿max
函数,我们在产品中找到最大值。
答案 1 :(得分:7)
这没有任何显式循环或调用max
函数。该函数假定输入列表中至少有五个元素并输出元组(start_index, max_product)
。
from functools import reduce, partial
import operator
def f(l):
win = zip(l, l[1:], l[2:], l[3:], l[4:])
products = map(partial(reduce, operator.mul), win)
return reduce(lambda x, y: x if x[1] > y[1] else y, enumerate(products))
In [2]: f([1, 2, 3, 4, 7, 8, 9])
Out[2]: (2, 6048)
In [3]: f([2, 6, 7, 9, 1, 4, 3, 5, 6, 1, 2, 4])
Out[3]: (1, 1512)
win = zip(l, l[1:], l[2:], l[3:], l[4:])
在输入列表上创建一个大小为5的滑动窗口迭代器。 products = map(partial(reduce, operator.mul), win)
是一个迭代器,在partial(reduce, operator.mul)
的每个元素上调用reduce(operator.mul, ...)
(转换为win
)。 reduce(lambda x, y: x if x[1] > y[1] else y, enumerate(products))
向products
添加一个计数器,并返回具有最高值的索引值对。
如果您需要更通用的版本和/或输入列表很大,您可以使用itertools.islice
:
from itertools import islice
def f(l, n=5):
win = zip(*(islice(l, i, None) for i in range(n)))
...
上面的代码在技术上使用了一个循环的生成器表达式。纯粹的功能版本可能看起来像
from itertools import islice
def f(l, n=5):
win = zip(*map(lambda i: islice(l, i, None), range(n)))
...
答案 2 :(得分:2)
您可以执行以下操作:
range(0, len(L) - 5)
start
的元组和项L[start:start + 5]
的产品L[result:result + 5]
这个算法可以进一步改进,以避免重新计算子产品,但使用&#34;滚动产品&#34;,当你从左到右减少时,更新,除以被删除的元素,并乘以添加的新元素。
答案 3 :(得分:0)
这是一个纯粹功能的Haskell解决方案:
import Data.List
multiply :: [Int] -> Int
multiply = foldr (*) 1
consecutiveProducts :: [Int] -> [(Int,Int)]
consecutiveProducts xs =
[(i,multiply $ take 5 h) | (i,h) <- zipped, length h >= 5]
where
indices = reverse [0..(length xs)]
zipped = zip indices (tails xs)
myComp (i1,h1) (i2,h2) = compare h2 h1
main = print $ head $ sortBy myComp $ consecutiveProducts [4,5,3,1,5,3,2,3,5]
这是它的作用:
tails xs
为所有以不同起始值开头的子集提供:
> tails [4,5,3,1,5,3,2,3,5]
[[4,5,3,1,5,3,2,3,5],[5,3,1,5,3,2,3,5],[3,1,5,3,2,3,5],[1,5,3,2,3,5],[5,3,2,3,5],[3,2,3,5],[2,3,5],[3,5],[5],[]]
zip
使用自然数,使得我们有一个与之关联的起始索引。multiply
函数。那些产品减少到一个数字。(5,450)
。答案 4 :(得分:0)
想要使用max而不使用max的一个衬垫
from numpy import prod
l=[2,6,7,9,1,4,3]
max([prod(l[i:i+5]) for i in range(len(l))])
sorted([prod(l[i:i+5]) for i in range(len(l))])[-1] // without max
答案 5 :(得分:0)
此解决方案使用reduce
计算5值产品,列表理解以生成所有这些产品,使用索引创建元组创建,再次reduce
以获得最佳元组
当输入中没有5个值时,if else
运算符用于捕获大小写。
from functools import reduce
def find_products(values):
return None if len(values) < 5 else reduce(
lambda best, this: this if this[1] > best[1] else best,
[(i, reduce(lambda a,b: a*b, values[i:i+5], 1)) for i in range(0, len(values)-4)]
)
result = find_products([1, 0, 8, 3, 5, 1, 0, 2, 2, 3, 2, 2, 1])
print (result)
示例调用的输出是:
(7, 48)
答案 6 :(得分:0)
势在必行的范例经常是:
state = state0
while condition:
# change state
对于很多人来说,这是编程的“自然”方式,你知道这样做是怎么做的。
纯functional paradigm禁止变量,它们有一些优点。它适用于通过参数(IN)和返回值(OUT)进行通信的函数。它经常使用递归函数。
通用的功能递归方案是:
f = lambda *args : result(*args) if condition(*args) else f(*newparams(*args))
在这里,我们可以找到以(l,i,imax,prodmax)
为参数的解决方案,并且:
condition = lambda l,i,_,__ : i>=len(l)-5
result = lambda _,__,*args : args
newparams = lambda l,i,imax,prodmax: (l, i+1, imax, prodmax) \
if l[i]*l[i+1]*l[i+2]*l[i+3]*l[i+4] <= prodmax \
else (l, i+1, i, l[i]*l[i+1]*l[i+2]*l[i+3]*l[i+4])
除了已经定义的函数之外没有。
您甚至无法定义任何功能,例如,请参阅here,但可读性会受到更多影响。
运行:
In [1]: f([random.randint(0,9) for i in range (997)],0,0,0)
Out[1]: (386, 59049)
Python通过将递归深度设置为2000来限制此方法,并通过隐藏模块functools
中的功能工具从Python 3中设置。
答案 7 :(得分:0)
使用recursion
首先,我们需要创建一个recursive
function
来查找product
的{{1}}:
list
我们可以做一些测试:
def product(l, i=0, s=1):
s *= l[i]
if i+1 < len(l):
return product(l, i+1, s)
return s
然后,我们可以在另一个>>> product([1, 2, 3])
6
>>> product([1, 1, 1])
3
>>> product([2, 2, 2])
8
function
中使用此recursive
来解决您的问题:
function
哪个有效!
以下是一些显示其有效的测试:
def find_products(l, i=0, t=(0, -1)):
p = product(l[i:i+5])
if p > t[1]:
t = (i, p)
if i+5 < len(l):
return find_products(l, i+1, t)
return t