flatten a level one list

Robin Becker robin at reportlab.com
Thu Jan 12 08:44:24 EST 2006


Peter Otten wrote:
> Tim Hochberg wrote:
> 
> 
>>Here's one more that's quite fast using Psyco, but only average without
>>it.
> 
>  
> 
>>def flatten6():
>>     n = min(len(xdata), len(ydata))
>>     result = [None] * (2*n)
>>     for i in xrange(n):
>>             result[2*i] = xdata[i]
>>             result[2*i+1] = ydata[i]
> 
> 
> 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

That's the winner for my machine and it works in the case I need :)

The numbers are microseconds/call

I used 20 reps and n from 10 up to 1000.

no psyco
      Name        10        20       100       200       500      1000
  flatten1   111.383   189.298   745.709  1397.300  3499.579  6628.775
  flatten2   142.923   209.496   907.182  1521.618  3565.397  7197.228
  flatten3   176.224   314.342  1385.958  2733.560  6726.693 12879.067
  flatten4   112.696   163.010   518.250   901.288  1979.749  3657.364
  flatten5    78.334   110.768   386.949   711.794  1617.664  3255.749
  flatten6   142.867   230.420   894.639  1767.012  4499.734  9017.906
flatten6a   163.093   263.330  1071.337  2084.287  5209.433 10383.610
flatten6b   180.582   275.761  1063.794  2074.705  5057.123 10043.567
flatten6c   167.898   253.664   974.202  1948.181  4821.339  9562.780
flatten6d   132.475   201.702   738.194  1406.659  3612.107  7242.038
  flatten7    59.030    62.354    90.347   130.771   254.613   438.994
  flatten8    88.978   173.737  1667.111  5674.297 28907.501 106330.749
flatten8a   107.388   225.951  2323.563  7088.136 34254.381 114538.384


psyco
      Name        10        20       100       200       500      1000
  flatten1    84.424   114.596   393.374   714.728  1809.448  3197.837
  flatten2   102.387   136.302   507.243   942.494  2276.770  4451.990
  flatten3    85.206   111.020   379.713   715.957  1607.104  3191.188
  flatten4   102.667   144.599   509.255   856.450  1839.591  3425.128
  flatten5    79.898   115.490   383.904   730.484  1739.411  3515.978
  flatten6    54.560    61.293   183.012   332.109   837.146  1604.366
flatten6a    79.647   108.114   405.107   752.917  1873.674  3824.620
flatten6b   111.746   132.978   473.189   907.378  2217.600  4257.357
flatten6c    98.756   110.629   376.724   730.037  1772.963  3524.247
flatten6d    59.253    69.199   172.731   295.820   717.577  1402.720
  flatten7    51.291    39.754    65.707   104.902   233.214   405.694
  flatten8    87.050   166.837  1665.407  5410.576 28459.567 107847.422
flatten8a   122.753   251.457  2766.944  7931.204 36353.503 120773.674

###############################
from itertools import izip
import timeit

_R=100

def flatten1(x, y):
     '''D Murman'''
     return [i for pair in izip(x, y) for i in pair]

def flatten2(x, y):
     '''D Murman'''
     return [i for pair in zip(x, y) for i in pair]

def flatten3(x, y):
     '''D Murman'''
     res = []
     for pair in izip(x, y):
         for i in pair:
             res.append(i)
     return res

# New attempts:
from itertools import imap
def flatten4(x, y):
     '''D Murman'''
     l = []
     list(imap(l.extend, izip(x, y)))
     return l


from Tkinter import _flatten
def flatten5(x, y):
     '''D Murman'''
     return list(_flatten(zip(x, y)))

def flatten6(x,y):
     '''Tim Hochberg'''
     n = min(len(x), len(y))
     result = [None] * (2*n)
     for i in xrange(n):
         result[2*i] = xdata[i]
         result[2*i+1] = ydata[i]
     return result

def flatten6a(x,y):
     '''Robin Becker variant of 6'''
     n = min(len(x), len(y))
     result = [None] * (2*n)
     for i in xrange(n):
         result[2*i:2*i+2] = xdata[i],ydata[i]
     return result

def flatten6b(x,y):
     '''Robin Becker variant of 6'''
     n = min(len(x), len(y))
     result = [None] * (2*n)
     for i,pair in enumerate(zip(xdata,ydata)):
         result[2*i:2*i+2] = pair
     return result

def flatten6c(x,y):
     '''Robin Becker variant of 6'''
     n = min(len(x), len(y))
     result = [None] * (2*n)
     for i,pair in enumerate(izip(xdata,ydata)):
         result[2*i:2*i+2] = pair
     return result

def flatten6d(x,y):
     '''Robin Becker variant of 6'''
     n = min(len(x), len(y))
     result = [None] * (2*n)
     j = 0
     for i in xrange(n):
         result[j] = xdata[i]
         result[j+1] = ydata[i]
         j+=2
     return result

from operator import add as operator_add
def flatten8(x,y):
     '''Paul Rubin'''
     return reduce(operator_add,zip(x,y),())

def flatten8a(x,y):
     '''Robin Becker variant of 8'''
     return reduce(operator_add,(xy for xy in izip(x,y)),())

def flatten7(x,y):
     '''Peter Otten special case equal lengths'''
     n = len(x)
     assert len(y) == n
     result = [None] * (2*n)
     result[::2] = x
     result[1::2] = y
     return result

funcs = [(n,v) for n,v in globals().items() if callable(v) and 
n.startswith('flatten')]
funcs.sort()

def testthem():
      res0 = funcs[0][1](xdata, ydata)
      for name,func in funcs:
          res = list(func(xdata, ydata))
          if res!=res0:
              print name,' fails', type(res0), type(res), res0[:5],res[:5], 
res0[-5:],res[-5:]

def timethem(D,n):
     for name,func in funcs:
         t = timeit.Timer(name+"(xdata,ydata)",'from __main__ import 
xdata,ydata,'+name)
         D.setdefault(name,{})[n] = 1e7*t.timeit(_R)/float(_R)

if __name__=='__main__':
     N = [10, 20, 100, 200, 500, 1000]
     xdata = range(N[-1])
     ydata = xdata[::-1]
     testthem()
     for p in 'no psyco','psyco':
         D={}
         if p=='psyco':
             import psyco
             psyco.full()
         for n in N:
             xdata = range(n)
             ydata = xdata[::-1]
             timethem(D,n)
         print '\n',p
         fmt = '%%%ds' % max(map(len,[x[0] for x in funcs]))
         print (fmt + len(N)*' %9d') % (('Name',)+tuple(N))
         fmt1 = fmt + len(N)*' %9.3f'
         for name,func in funcs:
             print fmt1 % tuple([name]+[D[name][n] for n in N])
         print
###############################
-- 
Robin Becker




More information about the Python-list mailing list