PyCV
PyCV

Reputation: 325

Python - Evenly divide numbers in a list of lists

How can, efficiently, a number be evenly distributed in 'n' groups?

I thought of this function, but it doesn't divide completely evenly this numbers.

def DivideList(total_num, div_num):

    div = int(total_num)/int(div_num)

    if (div_num < total_num):
        div_list = [[div*i, div*(i+1)] for i in range(div_num)]
        div_list[div_num-1][1] = total_num
    else:
        div_list = [[i, i+1] for i in range(total_num)]

    return div_list

print DivideList(100, 8)

Could this also be achieved with list comprehension?

EDIT:

Example:

DivideList(20, 4) >> [[0, 5], [5, 10], [10, 15], [15, 20]]

DivideList(14, 4) >> [[0, 4], [4, 8], [8, 11], [11, 14]]

Upvotes: 1

Views: 1748

Answers (3)

hxysayhi
hxysayhi

Reputation: 1987

Example1:

def DivideList(total_num, div_num):
    div = total_num / div_num
    left = total_num - div * div_num
    result = []
    m = 0
    for i in xrange(left):
        k = m
        m += (div + 1)
        result.append([k, m])

    for i in xrange(div_num - left):
        k = m
        m += div
        result.append([k, m])

    return result

More concise:

def DivideList(total_num, div_num):
    div = total_num / div_num
    left = total_num - div * div_num
    result = []
    for i in xrange(0, left*(div+1), div+1):
        result.append([i, i+div+1])

    for i in xrange(left*(div+1), total_num, div):
        result.append([i, i+div])

    return result

Example2: Here's a generator that yields the chunks you want:

def DivideList(total_num, div_num):
    div = total_num / div_num
    left = total_num - div * div_num
    m = 0
    for i in xrange(left):
        k = m
        m += (div + 1)
        yield [k, m]

    for i in xrange(div_num - left):
        k = m
        m += div
        yield [k, m]

More concise:

def DivideList(total_num, div_num):
    div = total_num / div_num
    left = total_num - div * div_num
    for i in xrange(0, left*(div+1), div+1):
        yield [i, i+div+1]

    for i in xrange(left*(div+1), total_num, div):
        yield [i, i+div]

Upvotes: 1

AkshayDandekar
AkshayDandekar

Reputation: 435

Old suggestion:

So if you are simply trying to force a float division, change your code as

div = 1.0*total_num/div_num

EDIT: So I am still unclear on your requirement, but my attempt is below. Also, does it have to be list comprehensions? really affects readability in this case. I managed to implement it in two list comprehensions.

def Segments(total_num,div_num):
    return [(total_num/div_num)+1 if(i<total_num%div_num) else (total_num/div_num) for i in range(div_num)]

def DivideList(series):
    return [[sum(series[0:i]),sum(series[0:i+1])] for i in range(len(series))]

print DivideList(Segments(100,8))

Maybe someone can shorten/beautify this further.

Upvotes: 0

brianpck
brianpck

Reputation: 8254

Here is one possibility for achieving the result. Please specify the corner cases you wish to handle, if this is not sufficient. For instance, it does not make sense to cast to int if the expected arguments are already ints, as in your example.

As suggested by ma3oun, np.linspace is an excellent way to achieve this:

>>> def divide_list(total_num, div_num):
...     temp = np.linspace(0, total_num, div_num + 1)
...     return list(zip(temp[:-1], temp[1:]))
...
>>> divide_list(100, 8)
[(0.0, 12.5), (12.5, 25.0), (25.0, 37.5), (37.5, 50.0), (50.0, 62.5), (62.5, 75.0), (75.0, 87.5), (87.5, 100.0)]

This produces even steps, unlike your last example:

>>> divide_list(20, 4)
[(0.0, 5.0), (5.0, 10.0), (10.0, 15.0), (15.0, 20.0)]
>>> divide_list(14, 4)
[(0.0, 3.5), (3.5, 7.0), (7.0, 10.5), (10.5, 14.0)]

My previous example using np.arange:

>>> import numpy as np
>>> def divide_list(total_num, div_num):
...     div = total_num / div_num
...     temp = np.arange(0, total_num + div, div)
...     return list(zip(temp[:-1], temp[1:]))
...
>>> divide_list(100, 8)
[(0.0, 12.5), (12.5, 25.0), (25.0, 37.5), (37.5, 50.0), (50.0, 62.5), (62.5, 75.0), (75.0, 87.5), (87.5, 100.0)]

Upvotes: 0

Related Questions