Сегментировать список в Python

Я ищу встроенную функцию (или механизм) Python для сегментации списка на требуемые длины сегментов (без изменения входного списка). Вот код, который у меня уже есть:

>>> def split_list(list, seg_length):
...     inlist = list[:]
...     outlist = []
...     
...     while inlist:
...         outlist.append(inlist[0:seg_length])
...         inlist[0:seg_length] = []
...     
...     return outlist
... 
>>> alist = range(10)
>>> split_list(alist, 3)
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]

person kjfletch    schedule 02.08.2009    source источник
comment
связанные stackoverflow.com/questions/1915170/   -  person jfs    schedule 21.05.2010


Ответы (3)


Вы можете использовать понимание списка:

>>> seg_length = 3
>>> a = range(10)
>>> [a[x:x+seg_length] for x in range(0,len(a),seg_length)]
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]
person OmerGertel    schedule 02.08.2009
comment
Вы также можете сделать это генератором, то есть (a[x:x+seg_length] для x в диапазоне (0,len(a),seg_length)), который будет более эффективным для больших последовательностей. - person mhawke; 04.08.2009

Как вам нужно использовать вывод? Если вам нужно только перебирать его, вам лучше создать итерируемый объект, который дает ваши группы:

def split_by(sequence, length):
    iterable = iter(sequence)
    def yield_length():
        for i in xrange(length):
             yield iterable.next()
    while True:
        res = list(yield_length())
        if not res:
            return
        yield res

Пример использования:

>>> alist = range(10)
>>> list(split_by(alist, 3))
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]

Это использует гораздо меньше памяти, чем попытка построить весь список в памяти сразу, если вы только перебираете результат, потому что он создает только одно подмножество за раз:

>>> for subset in split_by(alist, 3):
...     print subset
...
[0, 1, 2]
[3, 4, 5]
[6, 7, 8]
[9]
person Martijn Pieters    schedule 02.08.2009
comment
+1. Очень разумный подход. Я буду помнить об этом, если мои входные данные увеличатся в размере. - person kjfletch; 02.08.2009

не тот результат, я все еще думаю, что функция группировки полезна:

from itertools import izip_longest
def grouper(iterable, n, fillvalue=None):
    args = [iter(iterable)] * n
    return izip_longest(*args, fillvalue=fillvalue)

для Python2.4 и 2.5, у которых нет izip_longest:

from itertools import izip, chain, repeat
def grouper(iterable, n, padvalue=None):
    return izip(*[chain(iterable, repeat(padvalue, n-1))]*n)

некоторый демонстрационный код и вывод:

alist = range(10)
print list(grouper(alist, 3))

вывод: [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, Нет, Нет)]

person sunqiang    schedule 02.08.2009