我有一个分配给排名的名单,通常是排名重复。我想生成列表的所有排列,并按排序顺序保持排名。例如:
[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需要多少内存?
答案 0 :(得分:1)
以下是使用groupby
,permutations
和product
的{{3}}解决方案。因为它主要使用生成器,所以它在内存上应该不会太重。如果您不需要将结果作为列表,但是例如只是想迭代它,那么内存需求实际上应该是相当适度的。
如果你需要列表,你需要列表的内存,但不多。
但是我担心你的数字,单独的最终列表将太大而不适合记忆。循环将永远。
>> 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)]