web-dev-qa-db-ja.com

pythonマップおよびその他の機能ツールの使用

これはかなりn00bishですが、私はPythonで関数型プログラミングを学び/理解しようとしています。次のコード:

foos = [1.0,2.0,3.0,4.0,5.0]
bars = [1,2,3]

def maptest(foo, bar):
    print foo, bar

map(maptest, foos, bars)

生成するもの:

1.0 1
2.0 2
3.0 3
4.0 None
5.0 None

Q。 mapまたはpythonのその他の機能ツールを使用して、ループなしで以下を生成する方法はありますか?

1.0 [1,2,3]
2.0 [1,2,3]
3.0 [1,2,3]
4.0 [1,2,3]
5.0 [1,2,3]

補足として、fooとbarの間に依存関係がある場合、実装はどのように変化するでしょうか。例えば。

foos = [1.0,2.0,3.0,4.0,5.0]
bars = [1,2,3,4,5]

and print:

1.0 [2,3,4,5]
2.0 [1,3,4,5]
3.0 [1,2,4,5]
...

PS:if、loop、ジェネレーターを使用して単純に行う方法を知っていますが、機能ツールを使用して同じことを達成する方法を学びたいです。 maptestにifステートメントを追加したり、maptest内のバーに別のフィルターマップを適用したりするだけですか?

127
chiraj

最も簡単な方法は、barsをさまざまな関数に渡すのではなく、maptestから直接アクセスすることです。

foos = [1.0,2.0,3.0,4.0,5.0]
bars = [1,2,3]

def maptest(foo):
    print foo, bars

map(maptest, foos)

元のmaptest関数を使用すると、mapでラムダ関数を使用することもできます。

map((lambda foo: maptest(foo, bars)), foos)
55
sth

他の関数型言語に精通していますか?つまり、pythonが関数型プログラミングをどのように行うかを学習しようとしていますか、または関数型プログラミングについて学習し、pythonを車両として使用しようとしていますか?

また、リストの理解を理解していますか?

map(f, sequence)

以下と直接同等(*)です。

[f(x) for x in sequence]

実際、map()はかつてpython 3.0からの削除が予定されていたため、冗長であると考えられていました(それは起こりませんでした)。

map(f, sequence1, sequence2)

ほとんどと同等です:

[f(x1, x2) for x1, x2 in Zip(sequence1, sequence2)]

(シーケンスの長さが異なる場合の処理​​方法には違いがあります。ご覧のとおり、map()はシーケンスの1つがなくなるとNoneになり、Zip()は最も短いシーケンスが終わると停止します停止)

したがって、特定の質問に対処するために、結果を生成しようとしています。

foos[0], bars
foos[1], bars
foos[2], bars
# etc.

これを行うには、1つの引数を取り、それを出力し、その後にバーを続ける関数を作成します。

def maptest(x):
     print x, bars
map(maptest, foos)

または、次のようなリストを作成できます。

[bars, bars, bars, ] # etc.

元のmaptestを使用します。

def maptest(x, y):
    print x, y

これを行う1つの方法は、事前にリストを明示的に作成することです。

barses = [bars] * len(foos)
map(maptest, foos, barses)

または、itertoolsモジュールをプルすることもできます。 itertoolsには、Pythonで関数型の遅延評価プログラミングを行うのに役立つ多くの巧妙な関数が含まれています。この場合、itertools.repeatが必要です。これは、引数を繰り返し処理するときに引数を無期限に出力します。この最後の事実は、あなたがそうするなら:

map(maptest, foos, itertools.repeat(bars))

map()は引数の1つが出力を生成している限り継続するため、無限の出力が得られます。ただし、itertools.imapmap()と同じですが、最短の反復可能なものが停止するとすぐに停止します。

itertools.imap(maptest, foos, itertools.repeat(bars))

お役に立てれば :-)

(*)python 3.0では少し異なります。そこでは、map()は本質的にジェネレータ式を返します。

194
John Fouhy

探しているソリューションは次のとおりです。

>>> foos = [1.0, 2.0, 3.0, 4.0, 5.0]
>>> bars = [1, 2, 3]
>>> [(x, bars) for x in foos]
[(1.0, [1, 2, 3]), (2.0, [1, 2, 3]), (3.0, [1, 2, 3]), (4.0, [1, 2, 3]), (5.0, [
1, 2, 3])]

繰り返しごとに関数呼び出しのオーバーヘッドを回避するため、mapの使用よりもリスト内包表記([(x, bars) for x in foos]部分)を使用することをお勧めします(非常に重要な場合があります)。 forループで使用する場合は、ジェネレーター内包表記を使用することで速度が向上します。

>>> y = ((x, bars) for x in foos)
>>> for z in y:
...     print z
...
(1.0, [1, 2, 3])
(2.0, [1, 2, 3])
(3.0, [1, 2, 3])
(4.0, [1, 2, 3])
(5.0, [1, 2, 3])

違いは、ジェネレーターの内包表記が 遅延ロード であることです。

UPDATEこのコメントへの応答:

もちろん、バーをコピーするのではなく、すべてのエントリが同じバーリストであることを知っています。したがって、それらのいずれか(元のバーを含む)を変更すると、それらすべてが変更されます。

これは有効なポイントだと思います。これには2つの解決策があります。最も効率的なのは、おそらく次のようなものです。

tbars = Tuple(bars)
[(x, tbars) for x in foos]

タプルは不変であるため、このリスト内包表記(または、そのルートに行く場合はジェネレータ内包表記)の結果によってバーが変更されるのを防ぎます。本当にすべての結果を修正する必要がある場合、これを行うことができます:

from copy import copy
[(x, copy(bars)) for x in foos]

ただし、これはメモリ使用量と速度の両方の面で少し高価になる可能性があるため、実際にそれぞれに追加する必要がない限り、これに反対することをお勧めします。

30
Jason Baker

関数型プログラミングとは、副作用のないコードを作成することです。

マップは、機能リスト変換の抽象化です。それを使用して、何かのシーケンスを取得し、それを他の何かのシーケンスに変換します。

イテレータとして使用しようとしています。しないでください。 :)

Mapを使用して必要なリストを作成する方法の例を次に示します。より短い解決策があります(理解を使用するだけです)が、これはどのマップが少し良くなるかを理解するのに役立ちます:

def my_transform_function(input):
    return [input, [1, 2, 3]]

new_list = map(my_transform, input_list)

この時点では、データ操作のみを行っていることに注意してください。これで印刷できます:

for n,l in new_list:
    print n, ll

-「ループなし」の意味がわかりません。 fpは、ループを回避することではありません(リスト内のすべてのアイテムを調べるには、各アイテムにアクセスする必要があります)。副作用を回避し、バグを少なくすることです。

20
Dustin
>>> from itertools import repeat
>>> for foo, bars in Zip(foos, repeat(bars)):
...     print foo, bars
... 
1.0 [1, 2, 3]
2.0 [1, 2, 3]
3.0 [1, 2, 3]
4.0 [1, 2, 3]
5.0 [1, 2, 3]
12
import itertools

foos=[1.0, 2.0, 3.0, 4.0, 5.0]
bars=[1, 2, 3]

print Zip(foos, itertools.cycle([bars]))

map(function, *sequences)関数のパラメーターの概要は次のとおりです。

  • functionは関数の名前です。
  • sequencesは任意の数のシーケンスであり、通常はリストまたはタプルです。 mapはそれらを繰り返し同時にfunctionに現在の値を与えます。それが、シーケンスの数が関数のパラメーターの数と等しくなければならない理由です。

functionのパラメーターの一部を反復処理しようとしているが、他のパラメーターを一定に保とうとしているようですが、残念ながらmapはそれをサポートしていません。 古い提案 を見つけてそのような機能をPythonに追加しましたが、マップ構造は非常にクリーンで確立されているので、そのようなものが実装されることはないでしょう。

他の人が示唆しているように、グローバル変数やリスト内包表記のような回避策を使用してください。

6
Nikhil Chelliah

これはどう:

foos = [1.0,2.0,3.0,4.0,5.0]
bars = [1,2,3]

def maptest(foo, bar):
    print foo, bar

map(maptest, foos, [bars]*len(foos))
0
sun.huaiyu

これでいいですか?

foos = [1.0,2.0,3.0,4.0,5.0]
bars = [1,2,3]

def maptest2(bar):
  print bar

def maptest(foo):
  print foo
  map(maptest2, bars)

map(maptest, foos)
0
Chris