簡體   English   中英

如何使用 map 在 Python 中的步驟中組成函數列表並減少

[英]How to compose a list of functions in steps in Python using map and reduce

給定一個函數(函數)列表和一個 integer n,我試圖找出一種逐步組合它們的方法,並返回每個逐步結果的列表,如下所示:

compose_step([lambda x: x+3, lambda x: x+5, lambda x: x+1], 8) --> [8, 11, 16, 17]

所以,到目前為止,我已經想出了如何組成一個函數列表並返回結果如下:

def compose(functions, n):
    def compose2(f,g):
        return lambda x: f(g(x))
    composedFunction = functools.reduce(compose2, functions, lambda x: x)
    return composedFunction(n)

但是,我非常困惑如何跟蹤每個步驟並將其作為列表返回。 我假設我需要以某種方式使用 map 以便 map 每個逐步進入列表。 我還提出了一種將列表中的所有函數應用於 n 的方法:

def apply_all_functions(functions, n):
    answerList = list(map(methodcaller('__call__', n), functions)))
    return answerList

我正在考慮以某種方式使用 composeFunction function 來組成一個新的逐步函數列表,一直到完全組成 function,然后將其用作 apply_all_functions 的新列表以實現所需的結果。 但目前,我很困惑。

您可以將itertools.accumulate與組合函數一起使用

from itertools import accumulate

def compose(f, g):
    return lambda x: f(g(x))

funcs = [lambda x: x, lambda x: x+3, lambda x: x+5, lambda x: x+1]

print([f(8) for f in accumulate(funcs, compose)])
# [8, 11, 16, 17]

itertools.accumulate是要走的路,但如果你想知道如何自己做,這是一種方法

def apply_all (x, f = None, *fs):
  if f is None:
    return []
  else:
    next = f (x)
    return [ next ] + apply_all(next, *fs)

funcs = \
  [ lambda x: x
  , lambda x: x+3
  , lambda x: x+5
  , lambda x: x+1
  ]

print(apply_all(8, *funcs))
# [ 8, 11, 16, 17 ]

如果您需要原始問題中的表格

def apply_all (fs, x):
  if not fs:
    return []
  else:
    next = fs[0](x)
    return [ next ] + apply_all(fs[1:], next)

funcs = \
  [ lambda x: x
  , lambda x: x+3
  , lambda x: x+5
  , lambda x: x+1
  ]

print(apply_all(funcs, 8))
# [ 8, 11, 16, 17 ]

上述形式在fs[0]fs[1:] ,表明這可以表示為香草reduce

from functools import reduce

def apply_all (fs, x):
  def reducer (acc, f):
    (seq, x) = acc
    next = f (x)
    return (seq + [next], next)
  return reduce(reducer, fs, ([], x)) [0]

funcs = \
  [ lambda x: x
  , lambda x: x+3
  , lambda x: x+5
  , lambda x: x+1
  ]

print(apply_all(funcs, 8))
# [ 8, 11, 16, 17 ]

您還可以使用帶有初始值的itertools.accumulate

from itertools import accumulate


def compose(data, funcs):
    yield from accumulate(funcs, lambda data, f: f(data), initial=data)


funcs = [lambda x: x+3, lambda x: x+5, lambda x: x+1]
init = 8
print(list(compose(init, funcs)))
# [8, 11, 16, 17]

如果您不想要中間結果,可以使用functools.reduce做類似的事情。

這類似於@Patrick 的回答,但這里accumulate應用每個 function 並逐個產生逐步結果,而不是生成組合函數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM