【发布时间】:2019-06-06 11:22:01
【问题描述】:
我想解决以下问题:给定一个包含不同长度子列表的列表,比如L = [ [ 'a', 'b' ], [ 'c' ], [ 'd', 'e', 'f' ] ],构造所有组合,只包含每个子列表中的一个元素。所以[ 'a', 'c', 'd' ] 是正确的组合,但不是[ 'a', 'b', 'e' ]。有与子列表长度的乘积一样多的组合,这里有六个组合,简而言之(顺序不重要):cda, cdb, cea, ceb, cfa, cfb。
这个想法是采用一个任意子列表,而不是单例,采用补码并根据子列表长度从补码和所选子列表的一个成员中创建尽可能多的新子列表。现在继续获取另一个长度大于 1 的子列表,并递归执行此操作,直到所有子列表仅包含单例。在构造了所有寻找的组合之后,该递归必须结束。代码如下:
def break_bipartite_chain( var_list ):
print('a')
bbc = []
def recursive_break( var_list ):
print('b')
bipartite_chain = sorted( var_list , key=len , reverse=True )
LC = len( bipartite_chain )
LCF = len( bipartite_chain[ 0 ] )
complement_chain = []
for i in range( 0, LCF ):
complement_chain.append( bipartite_chain[ 1 : ] )
if LCF == 1:
print('c')
bbc.append( bipartite_chain )
return None
else:
print('d')
for i in range( 0 , LCF ):
complement_chain[i].append([ bipartite_chain[ 0 ][ i ] ])
LCC = len( complement_chain )
for i in range( 0 , LCC ):
print('e')
recursive_break( complement_chain[ i ] )
return None
bbc.append( recursive_break( var_list ) )
return bbc[:-1]
现在,代码可以正常工作并完成应有的工作(至少在我尝试的示例中),但我仍然对它并不完全满意,而且由于我是一个相对的 python 新手,我会建议任何 cmets,包括风格,否则关注以下问题:
它之所以有效,是因为 if 部分中最里面的“返回”。我不明白当我删除它时会发生什么,但它给出了一个 错误代码“IndexError:列表索引超出范围”?我想用这种风格保留 if 部分并不是一个很好的解决方案,但我在这个论坛上发现了一些其他人,他们建议使用“return”命令过早地脱离这种声明。有更好的解决方案吗?
最中间的'return' 似乎是不必要的,但无论我是否写它(它在两种情况下都有效),它都会写入一个'None' 作为结果,我通过在最外层的return 中切片将其删除。有没有办法完全抑制 None ?
虽然它有效,但我仍然不确定递归操作。我逐步跟踪了上面给出的示例(这就是打印命令存在的原因),这是合乎逻辑的。我可以预测解决方案的顺序,他们同意了。但递归通常看起来像魔术。有更清洁的解决方案吗?
第一个 for 循环可能不是必需的,我尝试了(i)不使用补码的这种乘法(并且稍后在第二个 for 循环中使用补码链.append),或者这样做(ii)使用
bipartite_chain[1:]*LCF,要么根本不工作(第一种情况),要么产生奇怪的行为,因为我要附加的条目也出现了 LCF 时间(第二种情况)。
最后,我认为可能有更好的解决方案?或者至少有一些小事情需要改进?
已经感谢您的任何建议。
【问题讨论】:
-
如果代码正常工作,那么更合适的发布位置是Code Review。
标签: python list recursion return