我需要一个给出列表L
和数字N
的算法,返回一个N
个较小列表的列表,其中子列表是“平衡的”。例子:
algo(range(1, 8), 3) -> [[1,2,3], [4,5], [6,7]]
algo(range(1, 6), 4) -> [[1,2], [3], [4], [5]]
algo(range(1, 12), 5) -> [[1,2,3], [4,5], [6,7], [8,9], [10, 11]]
如您所见,算法应该“更喜欢”输出中的第一个列表。
我已经尝试了几个小时,但我无法找到一个漂亮而简洁的算法。顺便说一句,这将在Python中实现,但它确实是我在此之后的算法。这是不作业,这是一个网站,它将在三列(Django)的列表中显示内容。
我从freenode上的#python得到了最好的答案,结果如下:
def split_up(l, n):
q, r = divmod(len(l), n)
def division_point(i):
return i * q + min(i, r)
return [l[division_point(i):division_point(i+1)] for i in range(n)]
不要问我为什么会这样。 :)尽管如此,我会给出最多票数的答案。
答案 0 :(得分:5)
这是我提出的代码,没有排序。如果输入没有排序,只需打一个lst.sort()。
我认为这很好,使用迭代器并使用islice来切断下一部分。
import itertools
def partlst(lst, n):
"""Partition @lst in @n balanced parts, in given order"""
parts, rest = divmod(len(lst), n)
lstiter = iter(lst)
for j in xrange(n):
plen = len(lst)/n + (1 if rest > 0 else 0)
rest -= 1
yield list(itertools.islice(lstiter, plen))
parts = list(partlst(range(1, 15), 5))
print len(parts)
print parts
答案 1 :(得分:1)
假设您希望输出在可能的情况下包含相等长度的列表,否则在开头给出优先级。子列表长度之间的差异不超过一个。
>>> l = [0, 1, 2, 3, 4, 5, 6]
>>> def algo(li, n):
a, b = divmod(len(li), n)
c = [a + 1] * b + [a] * (n-b)
s = 0
for i, j in enumerate(c):
c[i] = li[s:s+j]
s += j
return c
>>> algo(l, 3)
[[0, 1, 2], [3, 4], [5, 6]]
>>> algo(l, 4)
[[0, 1], [2, 3], [4, 5], [6]]
答案 2 :(得分:0)
如果我理解你的问题......你只需要在mod(n)下为每个列表添加一个项目,你有算法(范围(a,b),n)
所以你应该:
答案 3 :(得分:0)
这是对功能性爱好者的致敬:
def algo(l, n):
if n == 1: return [l]
q, r = divmod(len(l),n)
if r: q += 1
return [l[:q]] + algo(l[q:], n - 1)
这个有点小:
def algo(l, n):
k = l[:]
q, r = divmod(len(l),n)
return [[k.pop(0) for _ in [0] * m]
for m in [q + 1] * r + [q] * (n - r)]
答案 4 :(得分:0)
有点迟到了,但是......
def algo(l, n):
return [l[-(-len(l)*i//n):-(-len(l)*(i+1)//n)] for i in range(n)]
在旧版本的Python中使用/而不是//。