Python - 在列表列表中均匀划分数字

时间:2017-04-13 14:33:02

标签: python list list-comprehension divide

如何有效地将数字均匀地分布在'n'组中?

我想到了这个功能,但它没有完全平均分配这个数字。

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)

这可以通过列表理解来实现吗?

编辑:

示例:

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

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

3 个答案:

答案 0 :(得分:1)

例1:

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

更简洁:

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

例2: 这是一个产生你想要的块的生成器:

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]

更简洁:

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]

答案 1 :(得分:0)

这是实现结果的一种可能性。如果这还不够,请指定您希望处理的角落案例。例如,如果预期的参数已经是int,则转换为int是没有意义的,如示例所示。

正如ma3oun所建议的那样,np.linspace是实现这一目标的绝佳方式:

>>> 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)]

与上一个示例不同,这会生成偶数步骤:

>>> 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)]

我之前使用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)]

答案 2 :(得分:0)

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.