将清单大致等份的最佳方法是什么?例如,如果列表有7个元素,并将其分为2部分,我们希望其中一部分有3个元素,而另一部分应该有4个元素。
我正在寻找类似even_split(L, n)的东西,它将L分解为n部分。
def chunks(L, n):
""" Yield successive n-sized chunks from L.
"""
for i in range(0, len(L), n):
yield L[i:i+n]
上面的代码给出了3个块,而不是3个块。我可以简单地转置(遍历这个,取每列的第一个元素,称之为第一部分,然后取第二个元素,把它放在第二部分,等等),但这破坏了项目的顺序。
使用numpy实现。linspace方法。
只需指定要将数组分成的部分的数量。各部门的规模将几乎相同。
例子:
import numpy as np
a=np.arange(10)
print "Input array:",a
parts=3
i=np.linspace(np.min(a),np.max(a)+1,parts+1)
i=np.array(i,dtype='uint16') # Indices should be floats
split_arr=[]
for ind in range(i.size-1):
split_arr.append(a[i[ind]:i[ind+1]]
print "Array split in to %d parts : "%(parts),split_arr
给:
Input array: [0 1 2 3 4 5 6 7 8 9]
Array split in to 3 parts : [array([0, 1, 2]), array([3, 4, 5]), array([6, 7, 8, 9])]
只要你不想要像连续块这样愚蠢的东西:
>>> def chunkify(lst,n):
... return [lst[i::n] for i in xrange(n)]
...
>>> chunkify(range(13), 3)
[[0, 3, 6, 9, 12], [1, 4, 7, 10], [2, 5, 8, 11]]
在这种情况下,我自己编写了代码:
def chunk_ports(port_start, port_end, portions):
if port_end < port_start:
return None
total = port_end - port_start + 1
fractions = int(math.floor(float(total) / portions))
results = []
# No enough to chuck.
if fractions < 1:
return None
# Reverse, so any additional items would be in the first range.
_e = port_end
for i in range(portions, 0, -1):
print "i", i
if i == 1:
_s = port_start
else:
_s = _e - fractions + 1
results.append((_s, _e))
_e = _s - 1
results.reverse()
return results
Divide_ports(1,10,9)将返回
[(1, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9), (10, 10)]
这段代码为我工作(python3兼容):
def chunkify(tab, num):
return [tab[i*num: i*num+num] for i in range(len(tab)//num+(1 if len(tab)%num else 0))]
示例(适用于bytearray类型,但也适用于列表):
b = bytearray(b'\x01\x02\x03\x04\x05\x06\x07\x08')
>>> chunkify(b,3)
[bytearray(b'\x01\x02\x03'), bytearray(b'\x04\x05\x06'), bytearray(b'\x07\x08')]
>>> chunkify(b,4)
[bytearray(b'\x01\x02\x03\x04'), bytearray(b'\x05\x06\x07\x08')]
这将通过一个表达式将其拆分为相等的部分,同时保持顺序:
myList = list(range(18)) # given list
N = 5 # desired number of parts
[myList[(i*len(myList))//N:((i+1)*len(myList))//N] for i in range(N)]
# [[0, 1, 2], [3, 4, 5, 6], [7, 8, 9], [10, 11, 12, 13], [14, 15, 16, 17]]
各部分的差异不超过一个元素。把18分成5份,结果是3 + 4 + 3 + 4 + 4 = 18。