Python 带重复排序表的有效置换

Python 带重复排序表的有效置换,python,python-3.x,list,permutation,repeat,Python,Python 3.x,List,Permutation,Repeat,我有一个名单的名称分配给职级,往往与职级重复。我想生成列表的所有排列,并保持排序顺序。例如: [Sam(17), Harry(17), Bob(5), Sally(5)] 会产生 Sam(17), Harry(17), Bob(5), Sally(5) Sam(17), Harry(17), Sally(5), Bob(5) Harry(17), Sam(17), Bob(5), Sally(5) Harry(17), Sam(17), Sally(5), Bob(5) 本质上,对于每

我有一个名单的名称分配给职级,往往与职级重复。我想生成列表的所有排列,并保持排序顺序。例如:

[Sam(17), Harry(17), Bob(5), Sally(5)]
会产生

Sam(17), Harry(17), Bob(5), Sally(5)

Sam(17), Harry(17), Sally(5), Bob(5)

Harry(17), Sam(17), Bob(5), Sally(5)

Harry(17), Sam(17), Sally(5), Bob(5)
本质上,对于每个不同的等级组,都有n!组合。在这种情况下是2!*2.我很难找到一种有效的方法来排列8个等级中34个名字的列表

我试图找到2时内存不足!*2! * 4! * 2! * 2! *8! * 4! * 10! 不同的清单

是否有任何有效的方法生成此列表?python需要多少内存?

下面是一个使用
groupby
permutations
product
的解决方案。由于它主要使用生成器,所以内存应该不会太大。例如,如果您不需要将结果作为一个列表,但只想对其进行迭代,那么内存需求实际上应该是相当适度的

如果您需要列表,您将需要用于列表的内存,但仅此而已

但我担心,仅凭你们的数字,最终的名单就太大,无法载入记忆。循环将永远持续下去

>> import itertools, operator
>>> 
>>> data = *zip('Peter Paul Mary Jack Jill'.split(), (17, 17, 17, 4, 4)),
>>> data
(('Peter', 17), ('Paul', 17), ('Mary', 17), ('Jack', 4), ('Jill', 4))
>>> 
# group by rank
>>> groups = itertools.groupby(data, operator.itemgetter(1))
# extract the groups and generate all permutations of each of them
>>> permutations = map(itertools.permutations, map(operator.itemgetter(1), groups))
# form the cartesian product of the permutations, flatten out excess nesting
# convert inner generators to lists
>>> result = map(list, map(itertools.chain.from_iterable, itertools.product(*permutations)))
>>> for i in result:
...     print(i)
... 
[('Peter', 17), ('Paul', 17), ('Mary', 17), ('Jack', 4), ('Jill', 4)]
[('Peter', 17), ('Paul', 17), ('Mary', 17), ('Jill', 4), ('Jack', 4)]
[('Peter', 17), ('Mary', 17), ('Paul', 17), ('Jack', 4), ('Jill', 4)]
[('Peter', 17), ('Mary', 17), ('Paul', 17), ('Jill', 4), ('Jack', 4)]
[('Paul', 17), ('Peter', 17), ('Mary', 17), ('Jack', 4), ('Jill', 4)]
[('Paul', 17), ('Peter', 17), ('Mary', 17), ('Jill', 4), ('Jack', 4)]
[('Paul', 17), ('Mary', 17), ('Peter', 17), ('Jack', 4), ('Jill', 4)]
[('Paul', 17), ('Mary', 17), ('Peter', 17), ('Jill', 4), ('Jack', 4)]
[('Mary', 17), ('Peter', 17), ('Paul', 17), ('Jack', 4), ('Jill', 4)]
[('Mary', 17), ('Peter', 17), ('Paul', 17), ('Jill', 4), ('Jack', 4)]
[('Mary', 17), ('Paul', 17), ('Peter', 17), ('Jack', 4), ('Jill', 4)]
[('Mary', 17), ('Paul', 17), ('Peter', 17), ('Jill', 4), ('Jack', 4)]

您应该查看
itertools
;似乎您希望创建每个组,然后对它们的
排列进行
产品
。如果使用迭代器,则不必同时将整个列表存储在内存中。值得注意的是,这两个
操作符.itemgetter(1)
s的角色完全不同。分配名称可能会有所帮助,例如,第一次使用
get\u rank=operator.itemgetter(1)
,第二次使用类似于
group for rank,group in groupby(data,get\u rank)
。我还认为创建初始数据集的语法是一个不必要的细节,特别是考虑到它实际上甚至不是OP的结构;嗯。@jornsharpe很公平。由于我们两人同时编辑,您的一些编辑似乎丢失了。不用担心,我将(IMO)最重要的部分放回了。@Paul,对于最终的迭代器对象,我仍然可以访问和操作特定的单个元素吗?这听起来有点疯狂,但我想使用一个单独的元素作为一个函数的中介,从而生成一个分数。得分最低的排列是最佳排列。这可能吗?@S.Avenci您可以在它们上面循环,但不能无序访问它们。但你描述的很简单。如果分数函数
f
将排列作为其单个参数并返回一个数字,则只需执行
min(result,key=f)
即可获得最佳排列。如果你对发电机不熟悉,有一个问题:你只能使用一次,然后它们就用完了。