reduce()--what is it good for? (was: Re: reduce() anomaly?)

Alex Martelli aleax at aleax.it
Fri Nov 7 12:21:54 EST 2003


Georgy Pruss wrote:

> seq=[1,3,4,7]
> map( int.__sub__, seq[1:], seq[:-1] ) # nearly twice faster than
> ....zip.... for long arrays

If this is a race, then let's measure things properly and consider
a few more alternatives, shall we...?

[alex at lancelot xine-lib-1-rc2]$ python a.py
  reduce: 100 loops, best of 3: 13.8 msec per loop
     zip: 100 loops, best of 3: 18 msec per loop
    izip: 100 loops, best of 3: 7.6 msec per loop
      w2: 100 loops, best of 3: 7.1 msec per loop
     wib: 100 loops, best of 3: 12.7 msec per loop
    loop: 100 loops, best of 3: 8.9 msec per loop
     map: 100 loops, best of 3: 7.6 msec per loop

itertools.w2 is an experimental addition to itertools which I
doubt I'll be allowed to put in (gaining less than 10% wrt the
more general izip is hardly worth a new itertool, sigh).  But,
apart from that, map and izip are head to head, and the plain
good old Python-coded loop is next best...!  reduce is slowest.

My code...:


if __name__ != '__main__':
    def difs_reduce(seq):
        differences = []
        def neighborDifference(left, right, accum=differences.append):
            accum(right - left)
            return right
        reduce(neighborDifference, seq)
        return differences

    def difs_zip(seq):
        return [ b-a for a, b in zip(seq,seq[1:]) ]

    import itertools
    def difs_izip(seq):
        return [ b-a for a, b in itertools.izip(seq,seq[1:]) ]

    def difs_w2(seq, wib=itertools.w2):
        return [ b-a for a, b in wib(seq) ]

    def window_by_two(iterable):
            it = iter(iterable)
            last = it.next()
            for elem in it:
                    yield last, elem
                    last = elem

    def difs_wib(seq, wib=window_by_two):
        return [ b-a for a, b in wib(seq) ]

    def difs_loop(seq):
        differences = []
        it = iter(seq)
        a = it.next()
        for b in it:
            differences.append(b-a)
            a = b
        return differences

    def difs_map(seq):
        return map(int.__sub__, seq[1:], seq[:-1])

if __name__ == '__main__':
    import timeit
    bargs = ['-c', '-simport a', '-sx=range(9999)']
    funs = 'reduce zip izip w2 wib loop map'.split()
    for fun in funs:
        args = bargs + ['a.difs_%s(x)' % fun]
        print '%8s:' % fun,
        timeit.main(args)


Alex





More information about the Python-list mailing list