Альтернативный способ разбиения списка на группы из 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]
Ответы
Ответ 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 уникальных элементов, выбранных из последовательности популяций. Используется для случайной выборки без замены.