一组 map/filter/reduce 函数的干净代码

32

有没有一种简单的方法,在一行代码中编写一系列的map/filter/reduce函数?

例如,可以这样写,而不是:

reduce(lambda x, y: x*y, filter(lambda x: x>0, map(lambda x: x - 1, some_list)))

我正在寻找类似以下的内容:

some_list.map(lambda x: x -1, a).filter(lambda x: x>0).reduce(lambda x, y: x*y)

为什么你要把这么多东西放在一行里?有三行或更多行不好吗? - Marcin
3
@Marcin 这是暴露于Scala的影响所致... - iliasfl
1
这是 Python 中最奇怪的事情之一。当等效的 Java 代码更短时,你就知道它很疯狂了:list.stream().map(x-> x - 1).filter(x-> x > 0).reduce((x, y)-> x * y) - Santhosh
4个回答

25

PyFunctional 可以让你在通过 pip install PyFunctional 安装之后做到这一点。

from functional import seq

seq(some_list).map(lambda x: x -1, a).filter(lambda x: x>0).reduce(lambda x, y: x*y)

这个包可以做比那更多的事情,你可以在github.com/EntilZha/PyFunctional上查看。


9
如果您想使用外部库,请查找https://github.com/serkanyersen/underscore.py。这是一个Python版本的underscore.js。因此,您可以使用chain()方法开始filtermapreduce等操作,并通过value()方法获取结果。使用该库,您可以编写类似以下的代码:
from underscore import _
my_array = [10, 48, -1, 30, 20, 0]
result = _(my_array).chain().map(lambda x,*a: x - 1).filter(lambda x: x > 0).reduce(lambda x,y,*a: x*y, 1).value()

我在 Python 3.4.2 中进行了测试,似乎运行良好。


7
您可以使用自己的列表:
class Mylist(list):

    def __init__(self, l):
        list.__init__(self,l)

    def map(self, f):
        return Mylist(map(f, self[:]))

在这种情况下,我们只需将列表子类化为一个新的列表方法。然后,您可以将mapfilterreduce方法添加到类中。我已经展示了如何添加map方法。其他函数将非常相似。
请注意,在这种情况下,您可以随意链接mapfilter函数,但reduce方法通常不会产生一个列表,因此不能再链接函数了。
以下是一个示例输出:
In [16]: xx = Mylist([1,2,3])

In [17]: xx.map(lambda m: m*2).map(lambda m: m**2)
Out[17]: [4, 16, 36]

1
我最近遇到了这个“问题”。我目前在工作中使用Python,但我错过了Scala的函数式语法/风格。我从@ssm那里得到了灵感,并将其扩展到了一个初始版本的软件包,希望它能提供与数据上的函数调用链接相同的感觉。我非常乐意听取反馈意见,而且只是不久前完成了第一个版本:https://pypi.python.org/pypi/ScalaFunctional/0.0.0 和 https://github.com/EntilZha/ScalaFunctional - EntilZha

0

Pyterator 也可以做到这一点!

from pyterator import iterate

(
    iterate(some_list)
    .map(lambda x: x-1)
    .filter(lambda x: x>0)
    .reduce(lambda x, y: x*y)
)

你可以使用以下命令进行安装

pip install git+https://github.com/remykarem/pyterator#egg=pyterator

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接