[英]Generate permutations of size n from given list, where each permutations must contain all of the original values, possibly repeated
I was trying to create a small script that will take the list of elements and create all the possible permutations of its contents, while all those permutations may have repetitions and have to be of size n and contain all the original values.我试图创建一个小脚本,它将获取元素列表并创建其内容的所有可能排列,而所有这些排列可能有重复并且必须是大小为 n 并包含所有原始值。 I tried to use the
itertools
library but they don't have anything of use.我尝试使用
itertools
库,但它们没有任何用处。 Is there something simple I can do to achieve that?我可以做一些简单的事情来实现这一目标吗?
Here is an example for the list [0,1,2]
and n=3
:这是列表
[0,1,2]
和n=3
的示例:
[0,1,2]
[0,2,1]
[1,0,2]
[2,0,1]
[1,2,0]
[2,1,0]
For n=4
, something like [0,1,1,2]
will also be allowed in the output.对于
n=4
,output 中也将允许类似[0,1,1,2]
的内容。
The behavior you described can be implemented with the following function:您描述的行为可以使用以下 function 来实现:
def perms_with_duplicates(lst: list, n: int) -> Iterator:
"""
Generate permutations of ``lst`` with length ``n``.
If ``n`` is greater than the length of ``lst``, then the
resulting permutations will include duplicate elements
from ``lst``. All of the original elements of ``lst``
are guaranteed to appear in each output permutation.
"""
# Number of duplicate entries that the permutations can include.
num_dupl = max(n - len(lst) + 1, 1)
return itertools.permutations(lst * num_dupl, n)
Alternatively, if you need this to work over any sequence , instead of just for lists, you could use或者,如果您需要它来处理任何序列,而不仅仅是列表,您可以使用
def perms_with_duplicates(seq: Sequence, n: int) -> Iterator:
"""
Generate permutations of ``seq`` with length ``n``.
If ``n`` is greater than the length of `seq`, then the
resulting permutations will include duplicate elements
from ``seq``. All of the original elements of ``seq``
are guaranteed to appear in each output permutation.
"""
# Number of duplicate entries that the permutations can include.
num_dupl = max(n - len(seq) + 1, 1)
it_dupl = itertools.chain.from_iterable(
itertools.repeat(seq, num_dupl)
)
return itertools.permutations(it_dupl, n)
Both functions behave as follows.这两个函数的行为如下。 Note that for
n
less than or equal to the length of the input sequence, the functions behave exactly like itertools.permutations
.请注意,对于小于或等于输入序列长度的
n
,函数的行为与itertools.permutations
完全相同。
>>> l = [0, 1, 2]
>>> list(perms_with_duplicates(l, 3))
[(0, 1, 2), (0, 2, 1), (1, 0, 2), (1, 2, 0), (2, 0, 1), (2, 1, 0)]
>>> len(list(perms_with_duplicates(l, 4)))
360
>>> list(perms_with_duplicates(l, 4))
[(0, 1, 2, 0),
(0, 1, 2, 1),
(0, 1, 2, 2),
(0, 1, 0, 2),
(0, 1, 0, 1),
...
(1, 2, 1, 0),
(1, 2, 1, 0),
(1, 2, 1, 2),
(1, 2, 0, 0),
(1, 2, 0, 1),
...
(2, 1, 0, 2)]
There is itertools.combinations_with_replacement()
.有
itertools.combinations_with_replacement()
。 [ New in 3.1 ] [ 3.1 中的新功能]
If the sequence length n is equal to number of unique elements, as in your example, then trivially there can be no repetitions, so this would reduce to itertools.permutations()
如果序列长度 n 等于唯一元素的数量,如您的示例所示,那么通常不会有重复,因此这将减少到
itertools.permutations()
Else for the general case, use a list comprehension to filter the raw output from itertools.combinations_with_replacement()
:否则,对于一般情况,使用列表推导过滤来自
itertools.combinations_with_replacement()
的原始 output :
from itertools import combinations_with_replacement
elems = [0,1,1,2]
[comb for comb in combinations_with_replacement(elems, 4) if all(el in comb for el in elems)]
[(0, 0, 1, 2), (0, 0, 1, 2), (0, 1, 1, 2), (0, 1, 1, 2), (0, 1, 2, 2), (0, 1, 1, 2), (0, 1, 2, 2)]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.