【问题标题】:Recursive algorithm - extend vs creating new list with '+'递归算法 - 使用“+”扩展与创建新列表
【发布时间】:2016-08-02 18:42:24
【问题描述】:

所以我在下面有一个递归函数,它不断用字母表中的每个小写字母替换 '_' 字符,直到这些可能的小写字母的所有组合都替换了 '_' 字符。

简单示例

repl_underscores('__A')

>>>[a_A,b_A,c_A......aaA,abA,acA....zzA]

我让这个函数与 extend 一起构建列表,正如下面的评论所提到的,它反复就地修改相同的现有列表并完成工作。

为了练习,我想重写以在每次调用时构建一个新列表,并将该结果传递给连续的递归调用,目的是获得相同的结果。

它不起作用,我知道这与我在每次调用时都建立一个新列表这一事实有关,但我认为既然我在每次递归调用中传递了构建版本,我会没关系,因为这些调用会被通知更改。

我很难找出它在哪里坏了。我知道我可以通过修改同一个列表(通过可变默认值、全局变量或扩展)来使其工作,但我想在每次递归时建立一个新的干净列表。

def repl_underscores(letters,res=None):
    if res is None: res = list()
    if '_' not in letters: return res
    repl = [letters.replace('_',letter,1) for letter in string.ascii_lowercase]
    res = res + repl #using += works, due to extending being a mutation (same list referenced at each call)
    for each in repl:
        repl_underscores(each,res) #trying to pass modified list to keep building up
    return res

print(repl_underscores('__DER'))

【问题讨论】:

  • 您是否尝试使用print 语句来查看发生了什么?

标签: python algorithm recursion combinations


【解决方案1】:

最好不要修改函数参数,而是使用返回值构建(更函数式的风格)。只需稍微修改您的代码,它就可以按预期工作。

导入字符串

def repl_underscores(letters):
    res = list()
    if '_' not in letters: return res
    repl = [letters.replace('_',letter,1) for letter in string.ascii_lowercase]
    res += repl 
    for each in repl:
        res += repl_underscores(each) 
    return res

print(repl_underscores('__DER'))

【讨论】:

  • 我也喜欢这种方式,谢谢你的回复。
【解决方案2】:
res = res + repl #using += works, due to extending being a mutation (same list referenced at each call)

这一行是问题所在,您似乎已经猜到了。每次,在递归调用中,它都会分配一个新的本地列表,它不会保留对旧列表的引用,因此调用者不会收到更改通知。

幸运的是,您的函数已经返回了列表,所以让我们捕获它:

     res = repl_underscores(each,res) #trying to pass modified list to keep building up

【讨论】:

  • @Solaxun 没关系,我知道这一点是因为我几天前被它咬了。 :)
【解决方案3】:

只使用一个没有递归的函数:

from itertools import combinations_with_replacement, chain

def repl_underscores(letters):
    result = []
    for chars in combinations_with_replacement(string.lowercase, letters.count('_')):
        chars = chain(chars,[''])
        result.append(''.join(a+next(chars) for a in letters.split('_')))
    return result

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多