我需要一个生成器,它获取一组“代理”和一组“项”作为输入,并生成所有分区,其中每个代理都获得相同数量的项。例如:
>>> for p in equalPartitions(["A","B"], [1,2,3,4]): print(p)
{'A': [1, 2], 'B': [3, 4]}
{'A': [1, 3], 'B': [2, 4]}
{'A': [1, 4], 'B': [2, 3]}
{'A': [2, 3], 'B': [1, 4]}
{'A': [2, 4], 'B': [1, 3]}
{'A': [3, 4], 'B': [1, 2]}
对于两个代理,这很简单(假设项目数为偶数):
^{pr2}$对于三个探员来说,情况变得更加复杂:
^{3}$有没有更通用的解决方案,适用于任何数量的代理?在
下面是一个递归解决方案,它通过将适当数量的项分配给第一个代理,然后将问题的其余部分交给进一步的自身调用来实现:
在单个代理的简单情况下,我们生成一个字典并终止。在
如果有多个代理,我们:
将应分配给第一个代理的索引的所有组合生成到
items
中。将这些索引处的项按相反顺序从
items
的副本弹出到selection
,然后用[::-1]
将结果反转回来,以保持预期的顺序。对其余的代理和项递归调用
part()
。将我们已经做出的选择添加到这些递归调用生成的每个结果中,并生成该结果。
这就是它的作用:
^{pr2}$如您所见,它处理
items
不能在agents
之间等分的情况。此外,与各种基于permutations()
的答案不同,它不会浪费计算重复结果的工作量,因此运行速度比它们快得多。在如果您有一个},不是{},这是我们想要的)。在
permutations
函数,它可以处理输入中的重复元素,而不会在输出中产生重复的置换,那么您可以非常有效地做到这一点。不幸的是,itertools.permutations
没有做我们想做的事情(len(list(itertools.permutations('aaa')))
是{这是我为前面的问题编写的一个置换函数,它恰好对重复的输入值做了正确的处理:
现在,下面是如何使用它将项目分配给代理:
^{pr2}$第一行构建对我们代理的引用列表,其长度与项目列表的长度相同。每个代理重复的次数与它们将接收的项目数相同。如果
items
列表不能完全均匀地划分,我将添加一些额外的引用到前几个代理。如果愿意,可以添加其他内容(比如['extra'] * extra_items
)。在主循环在分配列表的排列上运行。然后,它运行一个内部循环,该循环将置换中的代理与相应的项相匹配,并将结果打包到所需格式的字典中。在
对于任意数量的代理或项目,该代码在时间和空间上都应该是渐近最优的。也就是说,它可能仍然很慢,因为它依赖于我用纯Python编写的
permutation
函数,而不是用C编写的更快的实现。也许有一种有效的方法可以使用itertools
来获得我们想要的排列,但我不太确定如何实现。在一个非常低内存的解决方案,但相当短和更“Python”。而且,词典在结果中的顺序是相当随意的
相关问题 更多 >
编程相关推荐