示例:给定k = 3和n = 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。
答案 0 :(得分:6)
您可以使用itertools.combinations_with_replacement
从可迭代输入中返回元素的r长度子序列 允许单个元素重复多次。
组合按字典顺序排序。所以,如果输入 可迭代的被排序,组合元组将被排序 订购。 从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)}
编辑:
按照您在评论中的要求,可以将此输出转换为所需的格式(递归嵌套的元组),如下所示:
from itertools import combinations_with_replacement, product
def recursively_nested(t):
if len(t) <= 2:
return t
else:
return recursively_nested(t[:-1]), t[-1]
k = 4
n = 3
valid = list(combinations_with_replacement(range(n), k))
out = [recursively_nested(t) for t in valid]
print(out)
# [(((0, 0), 0), 0), (((0, 0), 0), 1), (((0, 0), 0), 2), (((0, 0), 1), 1), (((0, 0), 1), 2), ...]
答案 1 :(得分:2)
我建议您使用itertools.product和字典(用于存储删除的元组):
from itertools import product
n, k = 3, 3
data = list(product(range(n), repeat=k))
result = {}
for t in data:
key = tuple(sorted(t))
result.setdefault(key, []).append(t)
print(list(result.keys()))
输出
[(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)]
请注意,字典的值是已删除的元组,例如
for key, value in result.items():
print(key, value)
输出
(0, 0, 0) [(0, 0, 0)]
(0, 0, 1) [(0, 0, 1), (0, 1, 0), (1, 0, 0)]
(0, 0, 2) [(0, 0, 2), (0, 2, 0), (2, 0, 0)]
(0, 1, 1) [(0, 1, 1), (1, 0, 1), (1, 1, 0)]
(0, 1, 2) [(0, 1, 2), (0, 2, 1), (1, 0, 2), (1, 2, 0), (2, 0, 1), (2, 1, 0)]
(0, 2, 2) [(0, 2, 2), (2, 0, 2), (2, 2, 0)]
(1, 1, 1) [(1, 1, 1)]
(1, 1, 2) [(1, 1, 2), (1, 2, 1), (2, 1, 1)]
(1, 2, 2) [(1, 2, 2), (2, 1, 2), (2, 2, 1)]
(2, 2, 2) [(2, 2, 2)]
答案 2 :(得分:0)
我将追求额外的目标,一个函数返回选定的列表,剩下的作为集合(而不是列表)。
from itertools import combinations_with_replacement, product
k=3
n=3
def extra_goal(k, n):
selected = list(combinations_with_replacement(range(n), k))
removed = set(product(range(n), repeat=k)) - set(selected)
return selected, removed
print(extra_goal(k, 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)],
{(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)})