Splitting a list to sublists with sizes given in another list

Viewed 114

I have these lists:

l1 = [a,b,c,d,e,f,g,h,i]
l2 = [1,3,2,3]

How can I split l1 this way?

[[a],[b,c,d],[e,f],[g,h,i]]

-The first element is a list of one element because of the 1 of l2
-The second element is a list of three elements because of the 3 of l2
-The third element is a list of two elements because of the 2 of l2
-The fourth element is a list of three elements because of the 3 of l2

I've tried using a function:

def divide(num, n):
        return [num[i*n : (i+1)*n] for i in range(len(num)//n)]  

x = divide(l2,1)
for i in range(len(l2)):
    z = x[i]
    divide(l1,z)

But it's not working...

5 Answers

Code

l1 = ['a','b','c','d','e','f','g','h','i']
l2 = [1,3,2,3]

start = 0
l = []
for i in l2:
    l.append(l1[start: start+i])
    start = start + i
print(l)

Output

[['a'], ['b', 'c', 'd'], ['e', 'f'], ['g', 'h', 'i']]
[[l1.pop(0) for x in range(i)] for i in l2]

Output

[['a'], ['b', 'c', 'd'], ['e', 'f'], ['g', 'h', 'i']]

Work with an explicit iterator and itertools.islice.

>>> l1 = list("abcdefghi")
>>> l2 = [1,3,2,3]
>>> itr = iter(l1)
>>> [list(islice(itr, None, x)) for x in l2]
[['a'], ['b', 'c', 'd'], ['e', 'f'], ['g', 'h', 'i']]

Using itr instead of l1 means that islice won't start reading from the beginning of l1 on each call.

You can use functools.partial to refactor this to make the list comprehension a little more readable:

>>> from functools import partial
>>> take = partial(islice, iter(l1), None)
>>> [list(take(x)) for x in l2]
[['a'], ['b', 'c', 'd'], ['e', 'f'], ['g', 'h', 'i']]

you could do it like this =

start = 0
sublists = []
for n in l2:
   to = start + n
   sublists.append(l1[start:to])
   start = to

Result is your desired list

Using enumerate with slicing , you can do it this way :

l1 = ['a','b','c','d','e','f','g','h','i']
l2 = [1,3,2,3]

for index, num in enumerate(l2):
  sum_up = sum(l2[:index])
  print(l1[sum_up:sum_up+num])
Related