2

Python(2.7)でiterableにいくつかのreduce関数を実行したいと思います。一例は、整数の反復可能性の上でminmaxを呼び出すことです。もちろん、最初の呼び出しの後に使い果たされるので、reduce(min, it)reduce(max, it)を同じiterableで呼び出すことはできません。ユニットテストのようなPythonのiterableで複数のreduce関数を効率的に呼び出す方法はありますか?

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)) 

(そして、あなた、そう:あなたはこのような何かにそれを一般化してねえ、それは、かなり気の利いただ、

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

そして、あなたが思う:だから、のような何かをすると思うかもしれませんあなたはこのような何か:)

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 

おっと。それではあなたはPythonの最適化の知恵を探しているスタックオーバーフローに来...

答えて

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 
関連する問題