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

I want to be able to execute a sequence, for example:

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

Use a function such as:

 my_paginated_sequence = get_rows(my_sequence, 3) 

To obtain:

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

This is what I came up with just thinking this through:

 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 
+7
python pagination paging
source share
4 answers

If you know that you have a cut 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 a result, you will of course use list(getrows_byslice(seq, 3)) or the like.

If you start with a general iterable, itertools recipes offer help with a 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 will need to call list , if, of course, the list is what you want).

Since you really want the last tuple to be truncated rather than filled, you need to โ€œtrimโ€ the final fill values โ€‹โ€‹from the most recent tuple.

+11
source share

This version works with any (possibly lazy and unsharp) iterative and creates a lazy iterable (in other words, it is a generator and works with all types of sequences, including other generators):

 import itertools def paginate(iterable, page_size): while True: i1, i2 = itertools.tee(iterable) iterable, page = (itertools.islice(i1, page_size, None), list(itertools.islice(i2, page_size))) if len(page) == 0: break yield page 

Some examples:

 In [61]: list(paginate(my_sequence, 3)) Out[61]: [['foo', 'bar', 'baz'], ['spam', 'eggs', 'cheese'], ['yogurt']] In [62]: list(paginate(xrange(10), 3)) Out[62]: [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]] 
+6
source share

The grouper function in itertools smart and concise; the only problem is that you may need to trim the results, as Alex Martelli noted. I would be inclined towards a decision in accordance with the answer of Michal Marchik, although I do not understand why this cannot be done much easier. This works for all cases that I can imagine:

 import itertools def paginate(seq, page_size): i = iter(seq) while True: page = tuple(itertools.islice(i, 0, page_size)) if len(page): yield page else: return 
+1
source share

If you are looking for understanding in a direct list, this will do the job:

 L = ['foo', 'bar', 'baz', 'spam', 'eggs', 'cheese', 'yogurt'] [L[i*3 : (i*3)+3] for i in range((len(L)/3)+1) if L[i*3 : (i*3)+3]] # [['foo', 'bar', 'baz'], ['spam', 'eggs', 'cheese'], ['yogurt']] L = ['foo', 'bar', 'baz', 'spam', 'eggs', 'cheese'] # [['foo', 'bar', 'baz'], ['spam', 'eggs', 'cheese']] 
0
source share

All Articles