Neater way of making indexes?
Steven Taschuk
staschuk at telusplanet.net
Sat May 31 00:23:14 EDT 2003
Quoth Jane Austine:
> The function returns a list of ordered indexes for nested for-loops of
> given input ranges.
>
> >>> from itertools import *
> >>> def indexes(upto):
> multi=lambda alist:reduce(lambda x,y:x*y,alist,1)
> g=[ cycle(chain(*[repeat(each,multi(upto[i+1:])) for each in
> range(upto[i])]))
> for i in range(len(upto))]
> return list(islice(izip(*g),multi(upto)))
>
> >>> indexes((4,))
> [(0,), (1,), (2,), (3,)]
> >>> indexes((3,2,4))
> [(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 0, 3), (0, 1, 0), (0, 1, 1), (0,
> 1, 2), (0, 1, 3), (1, 0, 0), (1, 0, 1), (1, 0, 2), (1, 0, 3), (1, 1,
> 0), (1, 1, 1), (1, 1, 2), (1, 1, 3), (2, 0, 0), (2, 0, 1), (2, 0, 2),
> (2, 0, 3), (2, 1, 0), (2, 1, 1), (2, 1, 2), (2, 1, 3)]
>
> I don't like this code too much. Any suggestions?
def indices(*limits):
ind = [0]*len(limits)
while True:
yield tuple(ind)
for i in range(len(limits)-1, -1, -1):
ind[i] += 1
if ind[i] < limits[i]:
break
ind[i] = 0
else:
break
This method is just counting with varying bases, carries as
appropriate, stopping when the carry goes past the most
significant digit.
There's a recipe for a slightly more general problem in the Python
Cookbook:
<http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/159975>
I can't recommend the original version, but Raymond Hettinger's
suggested simplification is quite easy on the eyes.
--
Steven Taschuk "The world will end if you get this wrong."
staschuk at telusplanet.net -- "Typesetting Mathematics -- User's Guide",
Brian Kernighan and Lorrinda Cherry
More information about the Python-list
mailing list