使用Python映射和其他功能工具
这非常完美,但我试图在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
问:有没有一种方法可以在python中使用map或任何其他功能工具来产生下列内容,而不会产生循环等
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]
并打印:
1.0 [2,3,4,5]
2.0 [1,3,4,5]
3.0 [1,2,4,5]
...
PS:我知道如何天真地使用if,loops和/或generator,但我想学习如何使用功能工具来实现相同的功能。 是否只是在maptest内部添加if语句来测试地图或将其他过滤地图应用于酒吧?
最简单的方法不是让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
使用lambda函数:
map((lambda foo: maptest(foo, bars)), foos)
你熟悉其他功能语言吗? 即你想了解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()
填充为None,而当最短序列停止时, zip()
停止)
所以,为了解决你的具体问题,你试图产生结果:
foos[0], bars
foos[1], bars
foos[2], bars
# etc.
你可以通过编写一个只有一个参数并打印它的函数来完成这个工作,接下来是条形码:
def maptest(x):
print x, bars
map(maptest, foos)
或者,您可以创建一个如下所示的列表:
[bars, bars, bars, ] # etc.
并使用您的原始maptest:
def maptest(x, y):
print x, y
一种方法是预先明确地建立列表:
barses = [bars] * len(foos)
map(maptest, foos, barses)
另外,你可以拉动itertools
模块。 itertools
包含许多巧妙的功能,可以帮助你在python中进行函数式的懒惰评估编程。 在这种情况下,我们需要itertools.repeat
,当您迭代它时,它将无限期地输出它的参数。 这最后一个事实意味着如果你这样做:
map(maptest, foos, itertools.repeat(bars))
你会得到无尽的输出,因为只要其中一个参数仍然产生输出, map()
一直持续下去。 然而, itertools.imap
就像map()
,但是一旦最短迭代停止就会停止。
itertools.imap(maptest, foos, itertools.repeat(bars))
希望这可以帮助 :-)
(*)在Python 3.0中有点不同。 在那里,map()基本上返回一个生成器表达式。
以下是您需要的解决方案:
>>> 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时使用list comprehension( [(x, bars) for x in foos]
的[(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])
不同之处在于生成器理解是延迟加载的。
更新回应此评论:
当然,你知道,你不会复制栏,所有的条目都是同样的栏列表。 所以如果你修改它们中的任何一个(包括原始小节),你都要修改它们。
我想这是一个有效的观点。 我可以想到有两种解决方案。 效率最高的可能是这样的:
tbars = tuple(bars)
[(x, tbars) for x in foos]
因为元组是不可变的,所以这将防止通过这个列表理解的结果(或者如果你去那个路由发生器理解)修改柱。 如果你真的需要修改每一个结果,你可以这样做:
from copy import copy
[(x, copy(bars)) for x in foos]
但是,这在内存使用和速度方面可能会有点贵,所以我会建议您不要这样做,除非您真的需要为它们中的每一个添加内容。
链接地址: http://www.djcxy.com/p/55179.html