zipWith Python中的模拟?

时间:2012-03-19 07:48:12

标签: python haskell

Python中Haskell的zipWith函数的类比是什么?

zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]

6 个答案:

答案 0 :(得分:49)

map()

map(operator.add, [1, 2, 3], [3, 2, 1])

虽然通常使用带zip()的LC。

[x + y for (x, y) in zip([1, 2, 3], [3, 2, 1])]

答案 1 :(得分:38)

如果您愿意,可以创建自己的,但在Python中我们主要做

list_c = [ f(a,b) for (a,b) in zip(list_a,list_b) ] 

因为Python本身并不具备功能。它恰好支持一些方便的习语。

答案 2 :(得分:10)

您可以使用地图:

>>> x = [1,2,3,4]
>>> y = [4,3,2,1]
>>> map(lambda a, b: a**b, x, y)
[1, 8, 9, 4]

答案 3 :(得分:6)

使用itertools的懒惰zipWith

import itertools

def zip_with(f, *coll):
    return itertools.starmap(f, itertools.izip(*coll))

此版本将zipWith的行为概括为任意数量的迭代。

答案 4 :(得分:4)

一般情况下,正如其他人所说,map和zip可以帮助你像在Haskel中一样复制zipWith的功能。

通常,您可以在两个列表中应用已定义的二元运算符或某个二元函数。使用Python的map / zip替换Haskel zipWith的示例

Input: zipWith (+) [1,2,3] [3,2,1] 
Output: [4,4,4] 

>>> map(operator.add,[1,2,3],[4,3,2])
[5, 5, 5]
>>> [operator.add(x,y) for x,y in zip([1,2,3],[4,3,2])]
[5, 5, 5]
>>> 

还有zipWith的其他变体,即zipWith3,zipWith4 .... zipWith7。要复制这些功能主义者,您可能需要使用izip和imap而不是zip和map。

>>> [x for x in itertools.imap(lambda x,y,z:x**2+y**2-z**2,[1,2,3,4],[5,6,7,8],[9,10,11,12])]
>>> [x**2+y**2-z**2 for x,y,z in itertools.izip([1,2,3,4],[5,6,7,8],[9,10,11,12])]
[-55, -60, -63, -64] 

如您所见,您可以操作任意数量的列表,但您仍然可以使用相同的程序。

答案 5 :(得分:3)

我知道这是一个老问题,但是......

已经说过,典型的python方式就像是

active

因此在代码中看到类似的行,大多数pythonistas都会理解。

还有(我认为)纯粹懒惰的例子:

results = [f(a, b) for a, b in zip(list1, list2)]

但是我相信starmap返回一个迭代器,所以你不能索引,或者多次执行该函数返回的内容。

如果您不是特别关注懒惰和/或需要多次索引或循环浏览新列表,这可能是您可能获得的一般目的:

import itertools

def zipWith(f, *args):
    return itertools.starmap(f, itertools.izip(*args))

并不是说您无法使用懒惰版本,但如果您已经建立了列表列表,也可以像这样调用该函数。

def zipWith(func, *lists):
    return [func(*args) for args in zip(*lists)]

或者像正常一样:

results = zipWith(func, *lists)

不知何故,该函数调用看起来比列表推导版本更简单,更容易理解。

看着这一点,这看起来奇怪地让人想起我经常写的另一个辅助函数:

results = zipWith(func, list1, list2)

然后可以写成:

def transpose(matrix):
    return zip(*matrix)

不是一个更好的版本,但我总觉得有趣的是,当以功能风格编写通用函数时,我经常发现自己会去,"哦。这只是我之前已经写过的函数的一般形式。"