flatten a level one list

Robin Becker robin at reportlab.com
Fri Jan 13 05:55:51 EST 2006


Peter Otten wrote:
......
> - You are padding twice -- once with None, and then with the real thing.
> 
> def interleave2(*args, **kw):
>      dopad = "pad" in kw
>      pad = kw.get("pad")
>      count = len(args)
>      lengths = map(len, args)
>      maxlen = max(lengths)
>      if not dopad and min(lengths) != maxlen:
>          raise ValueError
>      result = maxlen*count*[pad]
>      for ix, input in enumerate(args):
>          result[ix:len(input)*count:count] = input
>      return result
> 
> $ python -m timeit -s 'from interleave_spencer import xdata, ydata,
> interleave as i;xdata=xdata[:-1]' 'i(xdata, ydata, pad=None)'
> 10000 loops, best of 3: 69.7 usec per loop
> $ python -m timeit -s 'from interleave_spencer import xdata, ydata,
> interleave2 as i;xdata=xdata[:-1]' 'i(xdata, ydata, pad=None)'
> 10000 loops, best of 3: 46.4 usec per loop
> 
> Not overwhelming, but I expect the difference to grow when the arguments
> occupy a significant portion of the available memory.
> 
> Peter
very nice indeed; another generalization is to allow truncation as well

def interleave(*args,**kw):
     """Peter Otten flatten7 (generalized by Michael Spencer and Robin Becker)
     Interleave any number of sequences, padding shorter sequences if kw pad
     is supplied or truncating if truncate=True is specified

     >>> interleave([1,3,5], [2,4,6]) == [1,2,3,4,5,6]
     True
     >>> interleave([1,2,3]) == [1,2,3]
     True
     >>> interleave(*[[1,2,3]]*10) == [1]*10+[2]*10+[3]*10
     True
     >>> interleave(range(0,1000,2),range(1,1000,2)) == range(1000)
     True
     >>> interleave([1,2],[3,4,5])
     Traceback (most recent call last):
     ...
     ValueError: Minimum length=2 != Max length=3
     >>> interleave([1,3],[2,4,6], pad = None) == [1,2,3,4,None,6]
     True
     >>> interleave([1,3],[2,4,6],truncate=True) == [1,2,3,4]
     True
     >>> interleave([1,2],[3,4,5],pad='aaa',truncate=1)
     Traceback (most recent call last):
     ...
     AssertionError: Cannot specify both truncate=True and pad='aaa'
     """
     dopad = "pad" in kw
     pad = kw.get("pad")
     dotrunc = bool(kw.get('truncate',False))
     assert not (dotrunc and pad), \
         'Cannot specify both truncate=True and pad=%r' % pad
     count = len(args)
     lengths = map(len,args)
     maxlen = max(lengths)
     minlen = min(lengths)
     if dotrunc:
         result = minlen*count*[None]
         for ix, input in enumerate(args):
             result[ix::count] = input[:minlen]
     else:
         if not dopad and minlen!=maxlen:
             raise ValueError('Minimum length=%d != Max length=%d'
                     % (minlen,maxlen))
         result = maxlen*count*[pad]
         for ix, input in enumerate(args):
             result[ix:len(input)*count:count] = input
     return result

def _test():
     import doctest, interleave
     return doctest.testmod(interleave)

if __name__ == "__main__":
     _test()

-- 
Robin Becker




More information about the Python-list mailing list