4

注:コメントする前に、以下の「より良い更新」セクションをお読みください。ここには微妙な点があります。私が知る限り、与えられた答えはまだ文脈の中で機能していません。

機能が少し異なるpythonの「map」関数に類似したものを見つけようとしています。これは例によって最もよく説明されます。'map'関数は次のことを行います。

In [1]:    def f(x,y):
               return x+y
In [2]:    map(f, ['a','b','c'],['1','2','3'])

Out[2]:    ['a1', 'b2', 'c3']

それで、mapはfを新しい関数に変えます。それをf_zipperと呼びましょう。f_zipperは引数を圧縮し、圧縮された各ペアにfを適用します。

私が構築したいのは、次のように動作する「magical_map」と呼ぶ関数です。

In [1]:    def f(x,y):
               return x+y
In [2]:    magical_map(f, ['a','b','c'],'1')

Out[2]:    ['a1', 'b1', 'c1']

したがって、magical_mapはfを大量に呼び出します(最初の引数リストの要素ごとに1つ)が、それらすべてを2番目の引数にまとめます。

注:2番目の引数にアクセスできないため、いわば、真に機能的なソリューションが必要です。

つまり、後で行うことは、次の関数を作成することです。

intermed_func = functools.partial(magical_map, f)
final_func = functools.partial(intermed_func, arg_I_know)

次に、final_funcは次のように呼び出すことができます

final_func(last_min_arg)

そして戻る

[f(arg_I_know[0], last_min_arg), f(arg_I_know[1], last_min_arg), ...]

私は基本的に「magical_map」を構築する方法に困惑しています。どんな助けでも素晴らしいでしょう。私はこのテーマについて何かを見つけることができませんでした。

ありがとう!

より良い更新:

コンテキストで問題を解決することは、両方の引数が同時にわかっているときに機能する関数を単に作成するよりもはるかに困難です。問題は、このコンテキストでは不明であるということです。より正確には、次の「final_func」を3つの文字列すべてに分割して適用できるようにする必要があります。現在、「map」を使用すると、次の動作が得られます。

def splitfunc(string, arg):
    return string.split(arg)

intermed_func = functools.partial(map, splitfunc)
final_func = functools.partial(intermed_func, ["a_b","v_c","g,g"])

final_func("_")

Out[xx]: [['a', 'b'], ['v_c'], ['g,g']]

しかし、(以下のすべての方法で)提案されているようにmagical_mapを定義すると、エラーまたは誤った動作が発生します。例えば。

def magical_map(func, mylist, arg):
   return map(f, mylist, [arg]*len(mylist))

それから私は実行します:

intermed_func = functools.partial(magical_map, splitfunc)
final_func = functools.partial(intermed_func, ["a_b","v,c","g,g"])

final_func("_")

私は得る:

['a_b_', 'v,c_', 'g,g_']
4

5 に答える 5

7

この怠惰なバージョンはどうですか:

>>> def add(x,y):
...     return x+y
... 
>>> def magic_map(func,*args):
...     return itertools.starmap(func,itertools.izip(*args))  #just zip in python 3.
...
>>> list(magic_map(add,['a', 'b', 'c'], itertools.repeat('1')))
['a1', 'b1', 'c1']

zipで を使用して展開できるように、どちらかの引数に無限の iterable を渡すことができるように、 は 2 つのシリーズの短い方を取る必要があることに注意してくださいitertools.repeat。これも遅延評価されるので、2 つの無限 iterable を渡すこともでき、問題なく動作すると思います -- 返されたオブジェクト全体を実際に反復処理しようとしない限り ;-)


これは、あなたがしていることと同様のコンテキストでこれを使用する試みです (ただし、私はあなたがしていることを完全には理解していないため、これはかなりずれている可能性があります):

import itertools
import functools

def magic_map(func,*args):
    return itertools.starmap(func,itertools.izip(*args))  #just zip in python 3.

lst = ["a_b","v_c","g,g"]
print list(magic_map(str.split, lst, itertools.repeat('_')))

intermed_func = functools.partial(magic_map,str.split)
print list(intermed_func(lst ,itertools.repeat('_')))

final_func = functools.partial(intermed_func,lst)
print list(final_func(itertools.repeat('_')))

出力は次のとおりです。

[['a', 'b'], ['v', 'c'], ['g,g']]
[['a', 'b'], ['v', 'c'], ['g,g']]
[['a', 'b'], ['v', 'c'], ['g,g']]

これはあなたが望むものです(私は思います)。

于 2012-12-14T18:46:35.670 に答える
6

Python 3 では:

いつものように、それitertoolsは救助です:

>>> import itertools
>>> list(map(f, ['a','b','c'], itertools.repeat("1")))
['a1', 'b1', 'c1']

複数の値の場合は、itertools.cycle()

>>> list(map(f, ['a','b','c','d'], itertools.cycle("12")))
['a1', 'b2', 'c1', 'd2']
于 2012-12-14T18:35:41.190 に答える
4

を使用しitertools.repeatます。

def magic_map(f, l, v):
    return map(f, l, itertools.repeat(v, len(l))

次のように使用します。

>>> magic_map(f, ['a', 'b', 'c'], '1')
['a1', 'b1', 'c1']

編集:

mapthg435が指摘しているように、長い引数が終了するまで続きます。

于 2012-12-14T18:36:43.383 に答える
2

どうですか

from functools import partial
def map_with(f, it, **kwargs):
    return map(partial(f, **kwargs), it)

def f(x,y): 
    return x+y

print map_with(f, ['a', 'b', 'c'], y='1') # ['a1', 'b1', 'c1']
于 2012-12-14T18:42:19.867 に答える
2

これはどう?

def magical_map(func, list, arg):
    return map(func, list, [arg]*len(list))

実際には、これは 1 行の関数なので、個別に定義するのではなく、書き出すだけでもかまいません。

于 2012-12-14T18:35:59.800 に答える