Разделение списка на неравные группы?
Я знаю, как разбить список на четные группы, но у меня возникают проблемы с его разбиением на неравные группы.
В сущности, это то, что у меня есть: некоторый список, пусть назовите его mylist
, который содержит х элементов.
У меня также есть другой файл, который можно назвать его вторым_list, который выглядит примерно так:
{2, 4, 5, 9, etc.}
Теперь, что я хочу сделать, разделите mylist
на неравные группы по интервалу в second_list. Итак, я хочу, чтобы моя первая группа была первым 2-мя элементами mylist
, вторая группа должна быть следующими 4 элементами mylist
, третья группа должна быть следующими 5 элементами mylist
, четвертая группа - быть следующими 9 элементами `mylist и т.д.
Есть ли простой способ сделать это? Я попытался сделать что-то похожее, если вы хотите разбить его на четные группы:
for j in range(0, len(second_list)):
for i in range(0, len(mylist), second_list[j]):
chunk_mylist = mylist[i:i+second_list[j]]
Однако это не разбивает его, как я хочу. Я хочу, чтобы мои # подписок были len(second_list)
, а также правильно расставлены, и это дает намного больше, чем это (а также разбивается неправильно).
Ответы
Ответ 1
Это решение отслеживает, сколько элементов вы написали. Он сработает, если сумма чисел в second_list
больше, чем mylist
total = 0
listChunks = []
for j in range(len(second_list)):
chunk_mylist = mylist[total:total+second_list[j]]
listChunks.append(chunk_mylist)
total += second_list[j]
После этого listChunks
представляет собой список, содержащий подписи с длиной, найденной в second_list
.
Ответ 2
Вы можете создать итератор и itertools.islice:
mylist = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
seclist = [2,4,6]
from itertools import islice
it = iter(mylist)
sliced =[list(islice(it, 0, i)) for i in seclist]
Что даст вам:
[[1, 2], [3, 4, 5, 6], [7, 8, 9, 10, 11, 12]]
Когда i-элементы потребляются, они уходят, поэтому мы продолжаем получать следующие элементы i.
Не уверен, что должно произойти с любыми остальными элементами, если вы хотите добавить их, вы можете добавить что-то вроде:
mylist = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ,14]
seclist = [2, 4, 6]
from itertools import islice
it = iter(mylist)
slices = [sli for sli in (list(islice(it, 0, i)) for i in seclist)]
remaining = list(it)
if remaining:
slices.append(remaining)
print(slices)
Что даст вам:
[[1, 2], [3, 4, 5, 6], [7, 8, 9, 10, 11, 12], [13, 14]]
Или, наоборот, если их было недостаточно, вы могли бы использовать пару подходов для удаления пустых списков, одно внутреннее выражение генератора:
from itertools import islice
it = iter(mylist)
slices = [sli for sli in (list(islice(it, 0, i)) for i in seclist) if sli]
Или объединить с itertools.takewhile:
from itertools import islice, takewhile
it = iter(mylist)
slices = list(takewhile(bool, (list(islice(it, 0, i)) for i in seclist)))
Что для:
mylist = [1, 2, 3, 4, 5, 6]
seclist = [2, 4, 6,8]
предоставит вам:
[[1, 2], [3, 4, 5, 6]]
В отличие от:
[[1, 2], [3, 4, 5, 6], [], []]
То, что вы используете полностью, зависит от ваших возможных inouts и того, как вы хотели бы обрабатывать различные возможности.
Ответ 3
Неоднозначный подход:
>>> lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
>>> sec = [2, 4, 5]
>>> np.split(lst, np.cumsum(sec))
[array([0, 1]), array([2, 3, 4, 5]), array([ 6, 7, 8, 9, 10]), array([11])]
И вот подход Python3.X с использованием itertool.accumulate()
:
>>> lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
>>> sec = [2,4,6]
>>> from itertools import accumulate
>>> sec = list(accumulate(sec_lst))
>>> sec = [0] + sec + [None] if sec[0] != 0 else sec + [None]
>>>
>>> [lst[i:j] for i, j in zip(sec, sec[1:])]
[[0, 1], [2, 3, 4, 5], [6, 7, 8, 9, 10], [11]]
Ответ 4
Использование list-comprehensions вместе с нарезкой и sum()
функция (все основные и встроенные инструменты python):
mylist = [1,2,3,4,5,6,7,8,9,10]
seclist = [2,4,6]
[mylist[sum(seclist[:i]):sum(seclist[:i+1])] for i in range(len(seclist))]
#output:
[[1, 2], [3, 4, 5, 6], [7, 8, 9, 10]]
Если seclist
очень длинный, и вы хотите более эффективно использовать numpy.cumsum()
:
import numpy as np
cumlist = np.hstack((0, np.cumsum(seclist)))
[mylist[cumlist[i]:cumlist[i+1]] for i in range(len(cumlist)-1)]
и получить те же результаты
Ответ 5
subgroups = []
start=0
for i in second_list:
subgroups.append(mylist[start:start + i])
start = i + start
В конце subgroups
будут указаны нужные списки
Пример выполнения:
>>> mylist = [1,2,3,4,5,6,7,8,9,10,11,12]
>>> second_list = [2,4,5,9]
>>> subgroups = []
>>> start=0
>>> for i in second_list:
... subgroups.append(mylist[start:start + i])
... start = i + start
...
>>> subgroups
[[1, 2], [3, 4, 5, 6], [7, 8, 9, 10, 11], [12]]
Ответ 6
У Padriac есть лучшее решение IMO, но я добавлю этот хакерский лайнер, который не требует импорта:
>>> L = [1,2,3,4,5,6,7,8,9,10] # source list - could be any iterable
>>> S = [2,3,4] # group sizes - could be any iterable
>>> [ [ [ next(i) for k in range(j) ] for j in iter(S) ] for i in [iter(L)] ][0]
[[1, 2], [3, 4, 5], [6, 7, 8, 9]]