I know how to split a list into even groups, but I\'m having trouble splitting it into uneven groups.
Essentially here is what I have: some list, let\'s call it
You can create an iterator and 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]
Which would give you:
[[1, 2], [3, 4, 5, 6], [7, 8, 9, 10, 11, 12]]
Once i elements are consumed they are gone so we keep getting the next i elements.
Not sure what should happen with any remaining elements, if you want them added, you could add something like:
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)
Which would give you:
[[1, 2], [3, 4, 5, 6], [7, 8, 9, 10, 11, 12], [13, 14]]
Or in contrast if there were not enough, you could use a couple of approaches to remove empty lists, one an inner generator expression:
from itertools import islice
it = iter(mylist)
slices = [sli for sli in (list(islice(it, 0, i)) for i in seclist) if sli]
Or combine with itertools.takewhile:
from itertools import islice, takewhile
it = iter(mylist)
slices = list(takewhile(bool, (list(islice(it, 0, i)) for i in seclist)))
Which for:
mylist = [1, 2, 3, 4, 5, 6]
seclist = [2, 4, 6,8]
would give you:
[[1, 2], [3, 4, 5, 6]]
As opposed to:
[[1, 2], [3, 4, 5, 6], [], []]
What you use completely depends on your possible inouts and how you would like to handle the various possibilities.
This solution keeps track of how many items you've written. It will crash if the sum of the numbers in the second_list
is longer than 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]
After running this, listChunks
is a list containing sublists with the lengths found in second_list
.
A numpythonic approach:
>>> 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])]
And here is a Python3.X approach using 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]]
Using list-comprehensions together with slicing and sum() function (all basic and built-in tools of 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]]
If seclist
is very long and you wish to be more efficient use numpy.cumsum() first:
import numpy as np
cumlist = np.hstack((0, np.cumsum(seclist)))
[mylist[cumlist[i]:cumlist[i+1]] for i in range(len(cumlist)-1)]
and get the same results
Padriac has the best solution IMO, but I'll chime in with this hacky one liner that requires no imports:
>>> 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]]
subgroups = []
start=0
for i in second_list:
subgroups.append(mylist[start:start + i])
start = i + start
At the end subgroups
will contain the desired lists
Example run:
>>> 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]]