0

Suppose I have a list like this:

myList=['A','B','C','D','E','F','G','H','I','J','K']

So, suppose I want to process this list as n-batches. If n = 3, the I want a list called batchIdx [(0,3),(4,7),(8,10)] where each tuple points to the (start,end) indices of myList.

myList could be of variable length. THis is not simply dividing list into equally sized chunks. Its like using divmod().

Edit: I actually want to create a list that indexes into myList. I'll use those indices in a different part of my program.

What is the best way to implement this?

Wtower
  • 18,848
  • 11
  • 103
  • 80
HuckleberryFinn
  • 1,489
  • 2
  • 16
  • 26
  • 2
    Possible duplicate of [How do you split a list into evenly sized chunks in Python?](http://stackoverflow.com/questions/312443/how-do-you-split-a-list-into-evenly-sized-chunks-in-python) – styvane Apr 21 '16 at 15:00
  • Do you want to create `batchIdx` or you want to use `batchIdx` to index into `myList` ? – Jon Clements Apr 21 '16 at 15:01
  • 1
    So you want: `[(0, 3), (3, 6), (6, 9), (9, 12)]` or `[(0, 3), (3, 6), (6, 9), (9, 11)]` ? – Jon Clements Apr 21 '16 at 15:09
  • Hi Jon, I actually want to create a list that indexes into myList. I'll use those indices in a different part of my program. – HuckleberryFinn Apr 21 '16 at 15:17
  • Yes turns out the question wasn't very clear that `n` would be the _number of batches_, not the _size or length_ of the batches. Now that we know this, I've updated my answer. – bakkal Apr 21 '16 at 18:05

2 Answers2

2

Updated answer based on question edit:

This is not simply dividing list into equally sized chunks. Its like using divmod()

Here's my solution that returns the indices, that will divide a list of length l, into n batches:

def slice_indices(l, n):
    q, r = divmod(l, n)
    step = q + 1 if r else q
    return [(i, min(i+step, l)) for i in range(0, l, step)]

Let's see some indices first:

>>> slice_indices(l=11, n=3)
[(0, 4), (4, 8), (8, 11)]
# We get 3 batches, index covers [0, 11] so we pass.

>>> slice_indices(l=30, n=4)
[(0, 8), (8, 16), (16, 24), (24, 30)]
# We get 4 batches, and index covers [0, 30], so we pass.

Let's see your list indexed with this:

>>> [myList[slice(*s)] for s in slice_indices(l=11, n=3)]
[['A', 'B', 'C', 'D'], ['E', 'F', 'G', 'H'], ['I', 'J', 'K']]

And the doesn't break at the limits of n = 1 or n = l

>>> [myList[slice(*s)] for s in slice_indices(l=11, n=1)]
[['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K']] # 1 batch
>>> [myList[slice(*s)] for s in slice_indices(l=11, n=11)]
[['A'], ['B'], ['C'], ['D'], ['E'], ['F'], ['G'], ['H'], ['I'], ['J'], ['K']] # 11 batches
bakkal
  • 54,350
  • 12
  • 131
  • 107
0
[(i-n,i) for i in range(n,len(myList)+1,n+1)]
polku
  • 1,575
  • 2
  • 14
  • 11
  • This code, returns a list that create equally sized blocks of n. Not what I need. I want n number of slices / batches or chunks. So say my list has length 20. and my n = 3, what I need are the start, end indices that can be used to slice mylist into 3 batches, groups – HuckleberryFinn Apr 21 '16 at 15:25
  • Agree this code constraints the size of slices to `n`, not the number of batches to `n` – bakkal Apr 21 '16 at 18:01