示例:给定k = 3和n = 3,很容易生成所有3元组的列表,其条目为0或1或2:
[(0,0,0),(0,0,1),(0,0,2),(0,1,0),(0,1,1),(0,1,2),( 0,2,0),(0,2,1),(0,2,2),(1,0,0),(1,0,1),(1,0,2),(1, 1、0),(1、1、1),(1、1、2),(1、2、0),(1、2、1),(1、2、2),(2、0, 0),(2、0、1),(2、0、2),(2、1、0),(2、1、1),(2、1、2),(2、2、0) ,(2、2、1),(2、2、2)]
但是,在我的上下文中,元组(0,1,2),(0,2,1),(1,2,0),(1,0,2),(2,0,1),(2 ,1,0)都“相同”(以不同的顺序排列相同的条目),因此我只想保留其中之一。在这六个中,(0,1,2)是条目“按顺序”的那个,所以我只想保留那个。
同样,元组(0,1,1)(1,0,1),(1,1,0)都相同,所以我只想保留(0,1,1)。
目标:某些函数generate_my_tuples(n,k)
将生成所有长度为k的元组的列表,其条目均在range(n)中,但仅是每个可能元组的“有序”版本,如上所述。
对于上面的示例,我希望输出为:
[(0,0,0),(0,0,1),(0,0,2),(0,1,1),(0,1,2),(0,2,2),( 1,1,1),(1,1,2),(1,2,2),(2,2,2)]
作为一个额外的目标,如果该函数还创建了已删除的元组的列表,那将是很好的。
注释:当k = 2时,我可以看到如何执行此操作,因此每个元组只有一个“正确”和一个“不正确”顺序。但是,我看不到如何将其概括为任意k(其中,元组的“不正确”版本的数量甚至取决于元组中的条目)。在我的上下文中,我确实需要此函数来涵盖所有可能的n和k。
您可以使用itertools.combinations_with_replacement
从输入迭代返回元素的r长度子序列,允许单个元素重复多次。
组合按字典顺序排序。因此,如果对输入的iterable进行排序,则将按排序顺序生成组合元组。从itertools导入groups_with_replacement
k = 3 n = 3 list(combinations_with_replacement(range(n), k))
输出:
[(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 1, 1), (0, 1, 2), (0, 2, 2), (1, 1, 1), (1, 1, 2), (1, 2, 2), (2, 2, 2)]
如果还需要省略的元组,则可以使用生成所有可能的输出product
,并删除有效的输出:
from itertools import combinations_with_replacement, product k = 3 n = 3 valid = list(combinations_with_replacement(range(n), k)) omitted = set(product(range(n), repeat=k)) - set(valid) print(omitted)
输出:
{(0, 2, 0), (1, 2, 1), (1, 1, 0), (1, 2, 0), (2, 1, 0), (0, 1, 0), (1, 0, 0), (2, 2, 1), (2, 0, 2), (2, 1, 1), (1, 0, 1), (2, 2, 0), (2, 0, 1), (2, 1, 2), (0, 2, 1), (2, 0, 0), (1, 0, 2)}