我有工人和任务要做:
workers = ['peter', 'paul', 'mary']
tasks = range(13)
现在我想将任务拆分成块或批次的工作,这样每个工人就可以处理一个批次,并且做的工作量与其他人大致相同。在我的现实生活中,我想将批处理作业安排到计算场。批处理作业应该并行运行。实际的调度和调度是由商业级工具如 lsf 或 grid 完成的。
我期望的一些例子:
>>> distribute_work(['peter', 'paul', 'mary'], range(3))
[('peter', [0]), ('paul', [1]), ('mary', [2])]
>>> distribute_work(['peter', 'paul', 'mary'], range(6))
[('peter', [0, 3]), ('paul', [1, 4]), ('mary', [2, 5])]
>>> distribute_work(['peter', 'paul', 'mary'], range(5))
[('peter', [0, 3]), ('paul', [1, 4]), ('mary', [2])]
不同之处在于我想要这些功能,按顺序或优先顺序:
- 尽可能不使用
len
内部长数据结构 - 接受生成器
- 返回发生器
- 尽可能多地使用 stdlib 组件
关于要求的一些旁注:
- 没有故意的命令:我有同名的工人可以做多个批次(unix 主机名)。如果您的解决方案使用 dicts,那很好,因为我们总是可以通过批量枚举进行工作人员查找。
- 任意长度:worker 和 tasks 都可以是任何长度 >= 1 的迭代。并且它们不必像上面示例中所示的平均拆分,其中 Mary 只得到一个任务。
- 秩序:对我来说并不重要。我猜其他人可能更喜欢 [0,1]、[2,3]、[5] 之类的顺序,但我不在乎。如果您的解决方案可以保持或切换顺序,也许值得向其他人指出。
我试图解决itertools
这个特殊的问题,并想出了以下代码来说明这个问题:
from itertools import *
def distribute_work(workers, tasks):
batches = range(len(workers))
return [ ( workers[k],
[t[1] for t in i]
) for (k,i) in groupby(sorted(zip(cycle(batches),
tasks),
key=lambda t: t[0]),
lambda t: t[0]) ]
这满足 4.,但排序很可能违反 1.. 和 2./3。甚至没有想过。
可能有一些简单的解决方案,以我没有想到的方式组合一些 stdlib 组件。但也许不是。有接盘侠吗?