Search code examples
pythonrangedivide

Best way to separate range into n equal ranges in Python


I have the total number of elements in the range N and a number of chunks nb

I want to divide N into nb best possible equal ranges, with just the start number and the end number. So for example, N=24 and nb=5 should output:

0,5 5,10 10,15 15,20 20,24

While N=28 and nb=5 should output:

0,5 5,10 10,16 16,22 22,28  (the rest of `N/nb` division is equally distributed on the 3 last subranges)

Based on one comment, I have this method:

def partition(lst, n):
    division = len(lst) / n
    return [lst[round(division * i):round(division * (i + 1))] for i in range(n)]

def ranges(N, nb):
    return ["{},{}".format(r.start, r.stop) for r in partition(range(N), nb)]

>>> ranges(28, 5)
['0,6', '6,11', '11,17', '17,22', '22,28']

Is there a better way to do this?


Solution

  • It is surely simpler to calculate the start and stop numbers directly rather than slicing a range object to get them:

    def ranges(N, nb):
        step = N / nb
        return ["{},{}".format(round(step*i), round(step*(i+1))) for i in range(nb)]
    

    This is not as much more efficient than your code that it might look because slicing a range object takes only O(1) time, so your existing code is already asymptotically optimal. My version likely improves performance by some constant factor, but it may be small. I do think my version is also a lot clearer though, which may be more important than whatever performance change there might be.