Traversing through variable-sized lists

John Posner jjposner at optimum.net
Wed Feb 17 14:24:52 EST 2010


On 2/17/2010 1:10 PM, Andrej Mitrovic wrote:
> Hi,
>
> I couldn't figure out a better description for the Subject line, but
> anyway, I have the following:
>
> _num_frames = 32
> _frames = range(0, _num_frames) # This is a list of actual objects,
> I'm just pseudocoding here.
> _values = [0, 1, 2, 3, 4]
>
> I want to call a function of _frames for each frame with a _values
> argument, but in a way to "spread out" the actual values.
>
> I would want something similar to the following to be called:
>
> _frames[0].func(_values[0])
> _frames[1].func(_values[0])
> _frames[2].func(_values[0])
> _frames[3].func(_values[0])
> _frames[4].func(_values[1])
> _frames[5].func(_values[1])
> _frames[6].func(_values[1])
> _frames[7].func(_values[1])
> _frames[8].func(_values[2])
> ...etc...

The lines above show that you are using two different series of index 
values. Each function call (more properly, "method call") has the form:

   frames[INDEX_FROM_FIRST_SERIES].func(INDEX_FROM_SECOND_SERIES)

(I've dropped the underscores in the names, for simplicity.) You're 
getting hung up trying to keep the two series of index values in sync. 
But you don't really need to. More below ...

>
> Both the _values list and _frames list can be of variable and uneven
> size, which is what is giving me the problems. I'm using Python 2.6.
>
> I've tried the following workaround, but it often gives me inaccurate
> results (due to integer division), so I had to add a safety check:
>
> num_frames = 32
> values = [0, 1, 2, 3, 4]
> offset_step = num_frames / len(values)
>      for index in xrange(0, num_frames):
>          offset = index / offset_step
>          if offset>  offset_values[-1]:
>              offset = offset_values[-1]
>          frames[index].func(values[offset])
>
> There has to be a better way to do this. I'd appreciate any help.
> Cheers!

As you've shown above, a "for" loop takes care of the first series of 
index values:

   for index in xrange(num_frames):       # "0" arg unnecessary
       frames[index].func(INDEX_FROM_SECOND_SERIES)

The second series of index values needs to look like this:

   0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3 ...

The trick is not to worry about matching the second series to the first 
series. Instead, create an "infinite" second series using a Python 
generator, and use as many of its values as you need. Don't worry about 
the unused values, because the series isn't *really* infinite. :-)

Here's an easy way to create the generator

   import itertools
   second_series_gen = (i/4 for i in itertools.count())

Now, every time you need another number from this series, use its next() 
method. So the above code becomes:

   for index in xrange(num_frames):
       frames[index].func(second_series_gen.next())

-John



More information about the Python-list mailing list