2012-12-14 30 views
4

注意:请在评论之前阅读下面的“更新更新”部分。这里有一些微妙之处。据我所知,没有任何答案在上下文中有效。Python:试图折叠第二个参数的函数映射

我试图找到一个类似于python'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(一个在每个元素第一个参数列表),但它将它们全部折叠到第二个参数上。

注意:我需要一个真正的功能解决方案,可以这么说,因为我不能访问第二个参数。

即我什么都做以后是构建以下功能:

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'应用分割。现在,使用'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_'] 
+0

不,使用2.7。我看不出如何在上下文中轻松开发循环,但我会考虑这一点。 – user1904822

+0

P.S.对于删除评论感到抱歉。我是Stack Overflow的新手,显然我是一个web form dumba $$。 – user1904822

+0

评论被所有者永久删除。别担心...... :) – mgilson

回答

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采取两个系列的短,使得我们可以通过一个无限的迭代要么这个论据允许我们使用itertools.repeat扩展一个。这懒洋洋地评价为好,所以我想你甚至可以通过2个无限iterables和它的工作好 - 只要你不尝试实际遍历整个返回的对象;-)


这里是一个试图以类似于你在做什么上下文中使用这个(虽然我不完全理解你在做什么,所以这可能是遥远):

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']] 

这是你想要的(我认为)。

+0

+1,错过了这个,我会使用的解决方案。最好不要依赖于一个序列。 –

+0

我试过了,这在列出的应用程序中不起作用,因为我不知道第二个参数是在强制传递第一个参数的同一时间。 – user1904822

+0

@ user1904822 - 我不确定你的意思。看看我的编辑,看看它是否能够帮助你 - 另外,谢谢你帮我弄清楚'functools.partial'的功能;-)。我从来没有需要它,所以我从来没有打扰过,直到现在才知道它。 – mgilson

6

在Python 3:

像往常一样,这是itertools to the rescue

>>> 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'] 
+0

(+1)用于'itertools.cycle()',我不知道它是否存在。 – NPE

+0

@NPE:Darn,我只是把它改成了'itertools.repeat()',这使得更多感觉是否只有一个参数需要重复... –

+0

(+1)停留:) – NPE

2

这个怎么样?

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

实际上,因为这是一个单行函数,所以可能只是写出来而不是单独定义它。

+0

在更大的背景下,这个解决方案有一些有趣的地方。我正在发布一个后续。 – user1904822

+0

不起作用,请参阅上文。 – user1904822

+0

适用于我...编辑。 –

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'] 

编辑:

map,为thg435指出,云,直至不再争论结束。

+0

你试过了吗?因为我无法让它工作...... TypeError:不支持的操作数类型为+:'NoneType'和'str'' – mgilson

+0

@mgilson现在就试试吧 - 我误解了'map'是如何与不同的 - 加长迭代器。 –

+0

我认为最好的选择是将'l'的长度赋给'repeat()',这样做就是做'starmap(f,zip(l,repeat(v)))'。 –

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'] 
+0

列出的应用程序失败(请参阅评论更新)。即当我以这种方式定义magical_map,然后在更新中运行代码时,我得到TypeError:magical_map()只需要2个参数。 – user1904822