flatten a level one list

Michael Spencer mahs at telcopartners.com
Thu Jan 12 13:00:20 EST 2006


Peter Otten wrote:

> I you require len(xdata) == len(ydata) there's an easy way to move the loop
> into C:
> 
> def flatten7():
>     n = len(xdata)
>     assert len(ydata) == n
>     result = [None] * (2*n)
>     result[::2] = xdata
>     result[1::2] = ydata
>     return result
> 
> $ python -m timeit 'from flatten import flatten6 as f' 'f()'
> 1000 loops, best of 3: 847 usec per loop
> $ python -m timeit 'from flatten import flatten7 as f' 'f()'
> 10000 loops, best of 3: 43.9 usec per loop
> 
> Peter
Very nice observation, Peter.  Easily the "winner".  It reminds me of 
str.translate beating python loops in filtering applications: 
http://groups.google.com/group/comp.lang.python/msg/e23cdc374144a4bd


What's more, you can generalize your approach to any number of sequences and 
un-equal lengths, with only modest loss of speed:

def interleave(*args, **kw):
     """Peter Otten flatten7 (generalized by Michael Spencer)
     Interleave any number of sequences, padding shorter sequences if kw pad
     is supplied"""
     dopad = "pad" in kw
     pad = dopad and kw["pad"]
     count = len(args)
     lengths = map(len, args)
     maxlen = max(lengths)
     result = maxlen*count*[None]
     for ix, input in enumerate(args):
         try:
             result[ix::count] = input
         except ValueError:
             if dopad:
                 result[ix::count] = input + [pad]*(maxlen-lengths[ix])
             else:
                 raise
     return result


def test_interleave():
     assert interleave([1,3,5], [2,4,6]) == [1,2,3,4,5,6]
     assert interleave([1,2,3]) == [1,2,3]
     assert interleave(*[[1,2,3]]*10) == [1]*10+[2]*10+[3]*10
     assert interleave(range(0,1000,2),range(1,1000,2)) == range(1000)
     def raises(func,*args, **kw):
         exc = kw.get("exc", Exception)
         try:
             func(*args)
         except exc:
             return True
     assert raises(interleave,[1,2],[3,4,5])
     assert interleave([1,3],[2,4,6], pad = None) == [1,2,3,4,None,6]


def timethem():
     for n in [1000, 10000, 100000, 1000000]:
         x = range(n); y = range(n)
         print "List length: ",n
         for func in [flatten7, interleave]:
             print shell.timefunc(func, x, y)

  >>> timethem()
  List length:  1000
  flatten7(...)  6442 iterations, 77.62usec per call
  interleave(...)  5475 iterations, 91.33usec per call
  List length:  10000
  flatten7(...)  318 iterations, 1.57msec per call
  interleave(...)  315 iterations, 1.59msec per call
  List length:  100000
  flatten7(...)  25 iterations, 20.61msec per call
  interleave(...)  24 iterations, 21.06msec per call
  List length:  1000000
  flatten7(...)  3 iterations, 198.51msec per call
  interleave(...)  3 iterations, 198.91msec per call
  >>>


Michael




More information about the Python-list mailing list