[Tutor] converting a range to a list of lists where ... [simplifying a problem / functions / list slices]

Danny Yoo dyoo@hkn.eecs.berkeley.edu
Mon, 26 Aug 2002 14:34:09 -0700 (PDT)


On Mon, 26 Aug 2002, Jeff Kowalczyk wrote:

> I want to parameterize a range A to B, e.g.
> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
>
> to a list of lists of length parameter N (e.g. 7), but with the first list
> of length N-1, e.g.
> [[1,2,3,4,5,6],[7,8,9,10,11,12,13],[14,15,16,17,18,19,20]]
>
> I'd like to do this in a pythonic way, without regressing to integer
> loop counters, temporary variables, explicit indexing and such, but my
> knowledge of generators and list comprehension isn't fully er,
> comprehended yet.

Hmmm... I'd discourage a list comprehension approach for this problem,
because this problem isn't quite doing a mapping or a filtering operation
on our list.  That is, we're not transforming individual elements of our
list into new elements, but rather are clumping them together.  I also
feel that generators would not be of much help on this one, but I could be
wrong on this.

Consequently, I think I'd go for an integer loop counter and explicit list
slicing on this one.  *grin* Seriously, they aren't bad tools!
Comprehensions are just shortcuts, and we don't always have to use them.
In fact, if we're straining to stretch list comprehensions, we're probably
complicating matters.


Let's simplify your problem for the moment: let's say that we just wanted
to take a list and break it into sublists of length 'N'.  (We'll deal with
that first sublist length restriction in a moment.)

If we go at the simpler problem, then defining a sublist grouping function
isn't bad at all:

###
>>> def group_sublists(mylist, N):
...     sublists = []
...     i = 0
...     while i < len(mylist):
...         sublists.append(mylist[i:i+N])
...         i = i + N
...     return sublists
...
>>> group_sublists(range(20), 5)
[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11, 12, 13, 14],
 [15, 16, 17, 18, 19]]
###

While this doesn't solve the immediate problem, it's fairly close.  The
reason why it's nice to go after this simpler problem fist is because we
can now apply it toward your full problem in a pretty way:

###
>>> def group_special(mylist, N):
...     return [mylist[:N-1]] + group_sublists(mylist[N-1:], N)
...
>>> group_special(range(20), 7)
[[0, 1, 2, 3, 4, 5],
 [6, 7, 8, 9, 10, 11, 12],
 [13, 14, 15, 16, 17, 18, 19]]
###

No mess, no fuss.  *grin*



I hope this helps!