使用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

上一篇: Using python map and other functional tools

下一篇: How to instantiate a class given its name as a string?