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))、もちろんなどを使用します。

開始するものが一般的な iterable である場合、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(もちろん、リストが必要な場合は、これを呼び出す必要があります)。

実際には、最後のタプルを埋めるのではなく切り捨てる必要があるため、最後のタプルから末尾の fill-values を「トリム」する必要があります。

于 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 に答える
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 に答える