【问题标题】:Efficient way to call multiple reduce functions on an iterable in Python?在 Python 中的可迭代对象上调用多个 reduce 函数的有效方法?
【发布时间】:2016-07-27 20:58:35
【问题描述】:

我想在 Python (2.7) 中的可迭代对象上运行几个 reduce 函数。一个例子是调用minmax 对一个可迭代的整数。但是当然你不能在同一个迭代器上调用reduce(min, it)reduce(max, it),因为它在第一次调用后就已经用尽了。所以你可能会考虑做这样的事情:

reduce(lambda a, b: (min(a[0], b[0]), max(a[1], b[1])), ((x, x) for x in it))

你认为,嘿,这很漂亮,所以你把它概括成这样的:

from itertools import izip

def multireduce(iterable, *funcs):
    """:Return: The tuple resulting from calling ``reduce(func, iterable)`` for each `func` in `funcs`."""
    return reduce(lambda a, b: tuple(func(aa, bb) for func, aa, bb in izip(funcs, a, b)), ((item,) * len(funcs) for item in iterable))

(而且你喜欢单元测试,所以你包括这样的东西:)

import unittest
class TestMultireduce(unittest.TestCase):
    def test_multireduce(self):
        vecs = (
            ((1,), (min,), (1,)),
            (xrange(10), (min, max), (0, 9)),
            (xrange(101), (min, max, lambda x, y: x + y,), (0, 100, (100 * 101) // 2))
        )
        for iterable, funcs, expected in vecs:
            self.assertSequenceEqual(tuple(multireduce(iterable, *funcs)), expected)

但是当你尝试它时,你会发现它真的很慢:

%timeit reduce(min, xrange(1000000)) ; reduce(max, xrange(1000000))
10 loops, best of 3: 140 ms per loop
%timeit reduce(lambda a, b: (min(a[0], b[0]), max(a[1], b[1])), ((x, x) for x in xrange(1000000)))
1 loop, best of 3: 682 ms per loop
%timeit multireduce(xrange(1000000), min, max)
1 loop, best of 3: 1.99 s per loop

哎哟。那么你来 Stack Overflow 寻找 Python 优化的智慧......

【问题讨论】:

    标签: python performance functional-programming iterator reduce


    【解决方案1】:

    嗯,就是这样,这与可迭代对象的意义不符...

    def multireduce(iterable, *funcs):
        """:Return: The tuple resulting from calling ``reduce(func, iterable)`` for each `func` in `funcs`."""
        return tuple(imap(reduce, funcs, tee(iterable, len(funcs))))
    

    但是对于我的测试用例来说还是相当快的:

    %timeit multireduce(xrange(1000000), min, max)
    10 loops, best of 3: 166 ms per loop
    

    【讨论】:

      猜你喜欢
      • 2021-05-23
      • 2018-11-15
      • 1970-01-01
      • 2013-08-03
      • 2012-07-04
      • 1970-01-01
      • 2022-10-19
      • 2013-06-18
      • 2016-08-03
      相关资源
      最近更新 更多