Python – Split a List into Uneven Groups

listpythonpython-2.7splitsublist

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 mylist, that contains x elements.

I also have another file, lets call it second_list, that looks something like this:

{2, 4, 5, 9, etc.}

Now what I want to do is divide mylist into uneven groups by the spacing in second_list. So, I want my first group to be the first 2 elements of mylist, the second group to be the next 4 elements of mylist, the third group to be the next 5 elements of mylist, the fourth group to be the next 9 elements of `mylist, and so on.

Is there some easy way to do this? I tried doing something similar to if you want to split it into even groups:

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]]

However this doesn't split it like I want it to. I want to end up with my # of sublists being len(second_list), and also split correctly, and this gives a lot more than that (and also splits incorrectly).

Best Answer

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.