从给定列表生成大小为 n 的排列,其中每个排列必须包含所有原始值,可能重复

问题描述

我试图创建一个小脚本,它将获取元素列表并创建其内容的所有可能排列,而所有这些排列可能有重复,并且大小必须为 n 并包含所有原始值。我尝试使用 itertools 库,但它们没有任何用处。我可以做些什么简单的事情来实现这一目标吗?

以下是列表 [0,1,2]n=3 的示例:

[0,2]
[0,2,1]
[1,2]
[2,0]
[2,0]

对于 n=4输出中也允许出现类似 [0,2]内容

解决方法

您描述的行为可以通过以下函数实现:

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)

或者,如果您需要它处理任何 sequence,而不仅仅是列表,您可以使用

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)

这两个函数的行为如下。请注意,对于小于或等于输入序列长度的 n,函数的行为与 itertools.permutations 完全相同。

>>> l = [0,1,2]

>>> list(perms_with_duplicates(l,3))                                                                                                
[(0,2),(0,2,1),(1,0),(2,0)]

>>> len(list(perms_with_duplicates(l,4)))
360

>>> list(perms_with_duplicates(l,4))                                                                                                
[(0,...
 (1,...
 (2,2)]
,

itertools.combinations_with_replacement()。 [New in 3.1]

如果序列长度 n 等于唯一元素的数量,如在您的示例中,那么很可能没有重复,因此这将减少到 itertools.permutations()

对于一般情况,使用列表推导过滤 itertools.combinations_with_replacement() 的原始输出:

from itertools import combinations_with_replacement

elems = [0,2]

[comb for comb in combinations_with_replacement(elems,4) if all(el in comb for el in elems)]

[(0,2)]

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...