Подтвердить что ты не робот

Альтернативный способ разбиения списка на группы из n

Скажем, у меня есть список произвольной длины, L:

L = list(range(1000))

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

n = 25
for i in range(0, len(L), n):
    chunk = L[i:i+25]

Есть ли встроенная функция для этого, я не хватает?

Изменить: Ранние ответы перерабатывают мой цикл for в listcomp, что не является идеей; вы в основном даете мне мой точный ответ в другой форме. Я вижу, есть ли альтернативное средство для достижения этого, как гипотетический .split в списках или что-то в этом роде. Я также использую это как генератор в некотором коде, который я написал вчера вечером:

def split_list(L, n):
    assert type(L) is list, "L is not a list"
    for i in range(0, len(L), n):
        yield L[i:i+n]
4b9b3361

Ответ 1

A Python recipe (В Python 2.6 используйте itertools.izip_longest):

def grouper(n, iterable, fillvalue=None):
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return itertools.zip_longest(*args, fillvalue=fillvalue)

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

>>> list(grouper(3, range(9)))
[(0, 1, 2), (3, 4, 5), (6, 7, 8)]
>>> list(grouper(3, range(10)))
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, None, None)]

Если вы хотите, чтобы последняя группа была короче остальных, а не дополнялась fillvalue, то вы могли бы, например, измените код следующим образом:

>>> def mygrouper(n, iterable):
...     args = [iter(iterable)] * n
...     return ([e for e in t if e != None] for t in itertools.zip_longest(*args))
... 
>>> list(mygrouper(3, range(9)))
[[0, 1, 2], [3, 4, 5], [6, 7, 8]]
>>> list(mygrouper(3, range(10)))
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]

Ответ 2

Здесь вы идете:

list_of_groups = zip(*(iter(the_list),) * group_size)

Пример:

print zip(*(iter(range(10)),) * 3)
[(0, 1, 2), (3, 4, 5), (6, 7, 8)]

Если количество элементов не делится на N, но вы все равно хотите их включить, вы можете использовать izip_longest, но он доступен только с python 2.6

izip_longest(*(iter(range(10)),) * 3)

Результат - это генератор, поэтому вам нужно преобразовать его в список, если вы хотите его распечатать.

Наконец, если у вас нет python 2.6 и застрял в старой версии, но вы все равно хотите иметь тот же результат, вы можете использовать карту:

print map(None, *(iter(range(10)),) * 3)
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, None, None)]

Я хотел бы добавить сравнение скорости между различными представленными до сих пор методами:

python -m timeit -s 'from itertools import izip_longest; L = range(1000)' 'list(izip_longest(*(iter(L),) * 3))'
10000 loops, best of 3: 47.1 usec per loop

python -m timeit -s 'L = range(1000)' 'zip(*(iter(L),) * 3)'
10000 loops, best of 3: 50.1 usec per loop

python -m timeit -s 'L = range(1000)' 'map(None, *(iter(L),) * 3)'
10000 loops, best of 3: 50.7 usec per loop

python -m timeit -s 'L = range(1000)' '[L[i:i+3] for i in range(0, len(L), 3)]'
10000 loops, best of 3: 157 usec per loop

python -m timeit -s 'import itertools; L = range(1000)' '[list(group) for key, group in itertools.groupby(L, lambda k: k//3)]'
1000 loops, best of 3: 1.41 msec per loop

Понимание списка и группа с помощью методов заметно медленнее, чем zip, izip_longest и map

Ответ 3

Как насчет:

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

Ответ 4

Itertools.groupby - прекрасный инструмент, вот способ разбить список целых чисел просто с помощью целочисленного деления:

>>> for key, group in itertools.groupby(range(10), lambda k: k//3):
...  print key, list(group)
... 
0 [0, 1, 2]
1 [3, 4, 5]
2 [6, 7, 8]
3 [9]

(Список должен начинаться с 0, чтобы начать с полной группы.)

Ответ 5

n = 25    
list_of_lists = [L[i:i+n] for i in range(0, len(L), n)]

он дает вам список списков [[0..24], [25..49], ..]

Если len(L) % n не равно 0, последний элемент (list_of_lists[-1]) будет len (L)% n.

Ответ 6

Вот рекурсивная версия. Это неэффективно, потому что у Python есть ограничения на рекурсию, но эта версия иллюстрирует, что каждая задача может быть решена путем рекурсии.

def split_to_groups(l, n):
    assert (len(l) / n) < 998, "Can't split to {} groups".format(len(l) / n)
    if l == []:
        return []
    else:
        f = [l[:n]]
        f.extend(split_to_groups(l[n:], n))
        return f

Ответ 7

И если вы решаете их, random.sample(совокупность, k), Возвращает список длины k уникальных элементов, выбранных из последовательности популяций. Используется для случайной выборки без замены.