PythonのHaskellの zipWith 関数の類似物は何ですか?
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
必要に応じて自分で作成できますが、Python
list_c = [ f(a,b) for (a,b) in Zip(list_a,list_b) ]
as Pythonは本質的に機能的ではありません。たまたまいくつかの便利なイディオムをサポートしています。
map()
_map(operator.add, [1, 2, 3], [3, 2, 1])
_
LC with Zip()
が通常使用されますが。
_[x + y for (x, y) in Zip([1, 2, 3], [3, 2, 1])]
_
あなたはマップを使うことができます:
>>> x = [1,2,3,4]
>>> y = [4,3,2,1]
>>> map(lambda a, b: a**b, x, y)
[1, 8, 9, 4]
怠惰なzipWith
とitertools:
import itertools
def Zip_with(f, *coll):
return itertools.starmap(f, itertools.izip(*coll))
このバージョンでは、zipWith
の動作を任意の数のイテラブルで一般化します。
一般に他の人がマップについて言及しているように、ZipはHaskelのようにzipWithの機能を複製するのに役立ちます。
一般に、定義された2項演算子または2つのリストにある2項関数のいずれかを適用できます。HaskelzipWithをPythonのmap/Zipで置き換える例
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の他のバリエーションがあります。これらの機能主義者を再現するには、Zipとマップの代わりにizipとimapを使用することができます。
>>> [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]
ご覧のとおり、必要なリストをいくつでも操作でき、同じ手順を使用できます。
これは古い質問であることは知っていますが、...
典型的なpythonの方法は次のようなものになると既に言われています
results = [f(a, b) for a, b in Zip(list1, list2)]
コードにそのような行を表示すると、ほとんどのpythonistaは問題なく理解できます。
また、(私が思うに)純粋に怠惰な例がすでに示されています:
import itertools
def zipWith(f, *args):
return itertools.starmap(f, itertools.izip(*args))
しかし、私はstarmapがイテレーターを返すと信じているので、インデックスを付けたり、その関数が返すものを何度も通過したりすることはできません。
特に遅延に関心がない場合や、新しいリストを何度もインデックス化またはループ処理する必要がある場合、これはおそらく、次のような一般的な目的です。
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)
これは次のように書くことができます:
def transpose(matrix):
return zipWith(lambda *x: x, *matrix)
それほど優れたバージョンではありませんが、関数型のスタイルでジェネリック関数を書くときに、「ああ。これは、以前に書いた関数のより一般的な形式にすぎない」ということがよくあります。