11

我希望能够采取如下序列:

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

使用如下函数:

my_paginated_sequence = get_rows(my_sequence, 3)

要得到:

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

这就是我通过思考得出的结论:

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
4

4 回答 4

18

如果你知道你有一个可切片的序列(列表或元组),

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

这当然是一个生成器,所以如果你绝对需要一个列表作为结果,你list(getrows_byslice(seq, 3))当然会使用或类似的。

如果您开始使用的是通用可迭代对象,那么itertools 食谱会提供有关食谱的帮助grouper...:

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)

list(同样,如果你想要一个列表,你当然需要调用它)。

由于您实际上希望最后一个元组被截断而不是填充,因此您需要从最后一个元组“修剪”尾随填充值。

于 2010-09-19T04:37:53.947 回答
6

这个版本适用于任何(可能是惰性和不可切片的)可迭代对象并产生一个惰性可迭代对象(换句话说,它是一个生成器,适用于所有类型的序列,包括其他生成器):

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

一些例子:

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]]
于 2010-09-19T04:42:35.110 回答
3

文档中的grouper函数itertools简洁明了;正如 Alex Martelli 指出的那样,唯一的问题是您可能需要修剪结果。我倾向于按照 Michał Marczyk 的回答来解决问题,尽管我不明白为什么不能让它变得更简单。这适用于我能想到的所有情况:

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
于 2017-01-29T07:12:53.867 回答
2

如果您正在寻找直接的列表理解,这将完成这项工作:

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']]
于 2010-09-19T04:27:45.373 回答