Как лучше использовать Python для группировки списка элементов в группы определенного максимального размера? - PullRequest
2 голосов
/ 05 декабря 2009

Я хочу написать функцию, которая берет элементы из списка и группирует их в группы размером n.

Т.е. при n = 5 [1, 2, 3, 4, 5, 6, 7] станет [[1, 2, 3, 4, 5], [6, 7]].

Какой лучший идиоматический способ Python сделать это?

Ответы [ 4 ]

2 голосов
/ 05 декабря 2009

Вы можете сделать это:

[a[x:x+n] for x in range(0, len(a), n)]

(В Python 2 для эффективности используйте xrange; в Python 3 используйте range, как указано выше.)

1 голос
/ 05 декабря 2009

Решения, использующие диапазоны с шагами, работают только с последовательностями, такими как списки и кортежи (не итераторы). Они также не так эффективны, как могли бы, поскольку они обращаются к последовательности много раз, вместо того, чтобы повторять ее один раз.

Вот версия, которая поддерживает итераторы и выполняет итерации только один раз, создавая список списков:

def blockify(iterator, blocksize):
    """Split the items in the given iterator into blocksize-sized lists.

    If the number of items in the iterator doesn't divide by blocksize,
    a smaller block containing the remaining items is added to the result.

    """
    blocks = []
    for index, item in enumerate(iterator):
        if index % blocksize == 0:
            block = []
            blocks.append(block)
        block.append(item)
    return blocks

И теперь версия итератора, которая возвращает итератор кортежей, не имеет дополнительной памяти и позволяет выбирать, включать ли остаток. Обратите внимание, что вывод может быть преобразован в список через список (blockify (...)).

from itertools import islice

def blockify(iterator, blocksize, include_remainder=True):
    """Split the items in the given iterator into blocksize-sized tuples.

    If the number of items in the iterator doesn't divide by blocksize and
    include_remainder is True, a smaller block containing the remaining items
    is added to the result; if include_remainder is False the remaining items
    are discarded.

    """
    iterator = iter(iterator) # we need an actual iterator
    while True:
        block = tuple(islice(iterator, blocksize))
        if len(block) < blocksize:
            if len(block) > 0 and include_remainder:
                yield block
            break
        yield block
1 голос
/ 05 декабря 2009

Я не знаю хорошей команды для этого, но вот способ сделать это с пониманием списка:

l = [1,2,3,4,5,6,7]
n = 5
newlist = [l[i:i+n] for i in range(0,len(l),n)]

Редактировать: как заметил комментатор, я случайно поместил l [i: i + n] в список.

0 голосов
/ 05 декабря 2009
[a[n*k:n*(k+1)] for k in range(0,len(a)/n+1)]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...