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).
Python String split() Method The split() method splits a string into a list. You can specify the separator, default separator is any whitespace. Note: When maxsplit is specified, the list will contain the specified number of elements plus one.
To split a list into n parts in Python, use the numpy. array_split() function. The np. split() function splits the array into multiple sub-arrays.
Given a list of lists and list of length, the task is to split the list into sublists of given length. Method #1: Using islice to split a list into sublists of given length, is the most elegant way. # into sublists of given length. Method #2: Using zip is another way to split a list into sublists of given length.
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.
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
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With