2016-04-07 11 views
2

Python'da (2.7) yinelenen bir kaç işlevle birkaç azaltma işlevi çalıştırmak istiyorum. Bir örnek, yinelenen bir tamsayıda min ve max'u çağırıyor olabilir. Ama elbette, ilk aramadan sonra tükendiğinden, reduce(min, it) ve reduce(max, it)'u aynı yinelenebilirlikte arayamazsınız. böylece, birim testlerinin severBirden çok çağrı yapmak için etkili bir yol, Python'da yinelenen işlevlerde işlevleri azaltın mı?

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

(Ve: Yani böyle bir şey yapmak düşünebilir:

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

Ve Hey, bu oldukça şık var, düşünüyorum, bu yüzden böyle bir şey haline genelleme Eğer böyle bir şey

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) 

:) şunlardır Ama o zaman denemek ve bunu yavaş gerçektenfarkında:

%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 

Ouch. Öyleyse ... Python optimizasyon bilgelik arayan

cevap

1

Peki taşması Stack gelmek, orada ...

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

tür Iterables noktasını defeats bu, var Ama benim test için oldukça hızlıdır durumda:

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