昨天,我遇到了一个问题,需要在范围为5的迭代中计算组合。
我尝试创建自己的原始函数,而不是使用itertools.combination
。它看起来像:
def combine_5(elements):
"""Find all combinations in elements with range 5."""
temp_list = []
for i in elements:
cur_index = elements.index(i)
for j in elements[cur_index+1 : ]:
cur_index = elements.index(j)
for k in elements[cur_index+1 : ]:
cur_index = elements.index(k)
for n in elements[cur_index+1 : ]:
cur_index = elements.index(n)
for m in elements[cur_index+1 : ]:
temp_list.append((i,j,k,n,m))
return temp_list
然后我想也许我可以抽象一点,制作一个combine_n
函数。以下是我最初的蓝图:
# Unfinished version of combine_n
def combine_n(elements, r, cur_index=-1):
"""Find all combinations in elements with range n"""
r -= 1
target_list = elements[cur_index+1 : ]
for i in target_list:
cur_index = elements.index(i)
if r > 0:
combine_n(elements, r, cur_index)
pass
else:
pass
然后我被困在那里一整天,主要的问题是我无法在递归函数中正确传达一个值。我添加了一些修复一个问题的代码。但是因为它适用于每个递归循环,所以出现了新的问题。更多修复导致更多错误,恶性循环。
然后我去寻找itertools.combination
源代码的帮助。事实证明它没有使用递归技术。
您是否认为可以使用递归技术将此combine_5
函数抽象为combine_n
函数?你对它的实现有任何想法吗?
失败样本1:
def combine_n(elements, r, cur_index=-1):
"""Find all combinations in elements with range n"""
r -= 1
target_list = elements[cur_index+1 : ]
for i in target_list:
cur_index = elements.index(i)
if r > 0:
combine_n(elements, r, cur_index)
print i
else:
print i
这是我最近在一系列过于复杂的实验后的尝试 核心思想是:如果我能正确打印出来,我可以稍后将它们收集到一个容器中 但问题是,在嵌套for循环中,当较低的for循环命中一个空列表时
temp_list.append((i,j,k,n,m))
的{{1}}条款不起作用。
但是在combine_5
中,它仍然会打印上层for循环的内容 像combine_n([0,1],2)将打印FAILURE SAMPLE 1
我需要找到一种方法将这个空信息传达给上级for循环 到目前为止我还没弄明白。
答案 0 :(得分:1)
是的,通过递归可以做到这一点。你可以让combine_n返回一个元组列表,其中包含从索引cur_index开始的所有组合,并从cur_combo的部分组合开始,这是你在递归时构建的:
def combine_n(elements, r, cur_index=0, cur_combo=()):
r-=1
temp_list = []
for elem_index in range(cur_index, len(elements)-r):
i = elements[elem_index]
if r > 0:
temp_list = temp_list + combine_n(elements, r, elem_index+1, cur_combo+(i,))
else:
temp_list.append(cur_combo+(i,))
return temp_list
elements = list(range(1,6))
print = combine_n(elements, 3)
输出:
[(1, 2, 3), (1, 2, 4), (1, 2, 5), (1, 3, 4), (1, 3, 5), (1, 4, 5), (2, 3, 4), (2, 3, 5), (2, 4, 5), (3, 4, 5)]
for循环仅上升到len(元素)-r,因为如果你走得更远,那么剩下的元素就没有足够的元素来填充元组中的剩余位置。元组只会在最后一级递归时添加到列表中,然后通过返回temp_lists并在每个级别连接回顶部来传递回调用堆栈。