pythonpaginationdata-paging

Is this how you paginate, or is there a better algorithm?


I want to be able to take a sequence like:

my_sequence = ['foo', 'bar', 'baz', 'spam', 'eggs', 'cheese', 'yogurt']

Use a function like:

my_paginated_sequence = get_rows(my_sequence, 3)

To get:

[['foo', 'bar', 'baz'], ['spam', 'eggs', 'cheese'], ['yogurt']]

This is what I came up with by just thinking through it:

def get_rows(sequence, num):
    count = 1
    rows = list()
    cols = list()
    for item in sequence:
        if count == num:
            cols.append(item)
            rows.append(cols)
            cols = list()
            count = 1
        else:
            cols.append(item)
            count += 1
    if count > 0:
        rows.append(cols)
    return rows

Solution

  • If you know you have a sliceable sequence (list or tuple),

    def getrows_byslice(seq, rowlen):
        for start in xrange(0, len(seq), rowlen):
            yield seq[start:start+rowlen]
    

    This of course is a generator, so if you absolutely need a list as the result, you'll use list(getrows_byslice(seq, 3)) or the like, of course.

    If what you start with is a generic iterable, the itertools recipes offer help with the grouper 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)
    

    (again, you'll need to call list on this if a list is what you want, of course).

    Since you actually want the last tuple to be truncated rather than filled up, you'll need to "trim" the trailing fill-values from the very last tuple.