views:

82

answers:

3

What is the simplest and reasonably efficient way to slice a list into a list of the sliced sub-list sections for arbitrary length sub lists.

For example, if our source list is:

input = [1, 2, 3, 4, 5, 6, 7, 8, 9, ... ]

And our sub list length is 3 then we seek:

output = [ [1, 2, 3], [4, 5, 6], [7, 8, 9], ... ]

Likewise if our sub list length is 4 then we seek:

output = [ [1, 2, 3, 4], [5, 6, 7, 8], ... ]
+7  A: 
[input[i:i+n] for i in range(0, len(input), n)]        # use xrange in py2k

where n is the length of a chunk.

Since you don't define what might happened to the final element of the new list when the number of elements in input is not divisible by n, I assumed that it's of no importance: with this you'll get last element equal 2 if n equal 7, for example.

SilentGhost
+5  A: 

The documentation of the itertools module contains the following recipe:

import itertools

def grouper(n, iterable, fillvalue=None):
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return itertools.izip_longest(fillvalue=fillvalue, *args)

This function returns an iterator of tuples of the desired length:

>>> list(grouper(2, [1,2,3,4,5,6,7]))
[(1, 2), (3, 4), (5, 6), (7, None)]
sth
while this is working with any iterable, it doesn't seem to be as efficient (at least in my tests) as my code when applied to the given task.
SilentGhost
@SilentGhost, Premature optimization?
Mike Graham
@Mike: I beg your pardon?
SilentGhost
A: 

I like SilentGhost's solution.

My solution uses functional programming in python:

group = lambda t, n: zip(*[t[i::n] for i in range(n)])
group([1, 2, 3, 4], 2)

gives:

[(1, 2), (3, 4)]

This assumes that the input list size is divisible by the group size. If not, unpaired elements will not be included.

Wiktor Kolodziej
your second example is limited to python-2.x. in py3k `map` cannot take `None` as a first argument.
SilentGhost
@SilentGhost: you are right, I'm removing it though.
Wiktor Kolodziej