您如何均匀分发每个都有值的子列表?
我想将以下列表分发到3个列表中。
lst = [['a',10],['b',40],['c',10],['d',30],['e',20],['f',100],['g',90],['h',4]]
由于所有值的总和为304,因此三个列表应聚合为约101.3。
这是我想以某种形式制作的结果。
lst1 = [['g',90],['a',10]]
lst2 = [['f',100],['h',4]]
lst3 = [['b',40],['c',10],['d',30],['e',20]]
这是我到目前为止解决它的解决方案,但需要一些工作来加快速度。
def ListSum(lst):
lst = map(lambda subli: subli[1],lst)
return sum(lst)
def EvenlyDistribute(lst):
#put into bucket until reached, then move to the next bucket
Lst1 = []
Lst2 = []
Lst3 = []
for subli in lst:
try:
if ListSum(Lst1) < 100:
Lst1.append(subli)
elif ListSum(Lst2) < 100:
Lst2.append(subli)
else:
Lst3.append(subli)
except:
pass
print Lst1
print Lst2
print Lst3
答案 0 :(得分:3)
这是一个简单的实现。首先,按权重对输入列表进行排序,然后枚举,将每个项目添加到最少的完整存储桶中。
def EvenlyDistribute(lst, n):
"""Distribute items in lst (tuples of (val, weight)) into n buckets"""
buckets = [[] for i in range(n)]
weights = [[0, i] for i in range(n)]
for item in sorted(lst, key=lambda x: x[1], reverse=True):
idx = weights[0][1]
buckets[idx].append(item)
weights[0][0] += item[1]
weights = sorted(weights)
return buckets
所以
for i, v in enumerate(EvenlyDistribute(lst, 3)):
print(v)
返回
[['f', 100], ['h', 4]]
[['g', 90], ['a', 10]]
[['b', 40], ['d', 30], ['e', 20], ['c', 10]]
答案 1 :(得分:0)
一个起点紧紧地提出这个问题是用组合技术强制它。为此你可以使用itertools。首先计算列表的所有排列(),然后使用组合()检查每个排列的所有可能组合,这些组合可以为每个排列提供可能的切片点。
然后,您可以检查每个子列表(sl0-2)的总和的方差,如其他答案所示。然后保留方差最小的那个,并在过程结束时返回。
from itertools import permutations, combinations
for perm in permutations(grades):
for i in combinations(xrange( len(grades)), 3):
sl0, sl1, sl2 = perm[i[0]:i[1]], perm[i[1]:i[2]], perm[i[2]:]
根据您的列表大小,这需要一些时间,当然,它可以很容易地同时编程,例如让每个进程计算以某个数字开头的排列,但我会留下怎么做那是另一个问题。修剪也是可能的。