2017-04-13 110 views
1

如何有效地將數字均勻分佈在「n」個組中?Python - 將列表中的數字均勻劃分爲列表

我想到了這個功能,但它並沒有完全均勻地分配這個數字。

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

+0

請發表您想要的結果 – Ajax1234

+0

也請提你想什麼來實現 –

+2

你有沒有考慮使用numpy.linspace樣品的例子嗎?它可以使用與您正在查找的參數類似的參數以常規方式生成數字。更多的信息在這裏: https://docs.scipy.org/doc/numpy/reference/generated/numpy.linspace.html – ma3oun

回答

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

這裏是一種可能實現的結果。請指明您希望處理的角落案例,如果這還不夠。例如,如果預期的參數已經是int s,那麼投射到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)] 
0

Old sugg estion:

所以,如果你只是想迫使浮師, 改變你的代碼

div = 1.0*total_num/div_num 

編輯:所以我還是對你的要求還不清楚,但我嘗試在下面。此外,它是否必須是列表解析?在這種情況下真正影響可讀性。我設法在兩個列表解析中實現它。

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

也許有人可以進一步縮短/美化它。

0

如果你想得更多,你會發現它是一個數學問題。不需要列表理解。 看到吹。

import math 
def DivideList(total_num, div_num): 
    num = math.ceil(total_num/div_num) 
    # result = [] 
    # for i in range(div_num - 1): 
    #  result.append([num*i,num*(1+i)]) 
    result = [[num*i,num*(i+1)] for i in range(div_num-1)] 
    result.append([(div_num-1)*num,total_num]) 
    return result