在递归函数中保持变量的初始值

时间:2016-12-19 13:31:49

标签: python variables recursion

我正在编写一个递归函数,它将采用两个字符串tbl2 <- tbl %>% filter(!is.numeric(col1)) sub。我必须找出stringsub的子字符串。

递归函数是一项严格的要求,无法删除。

这是我尝试过的,但它已经破了:

string

在以下情况下返回def is_substring(sub,string): if sub=="": return True if string=="": return False if sub[0]==string[0]: return is_substring(sub[1:],string[1:]) if sub[0]!=string[0]: return is_substring(sub,string[1:]) 而不是True

False

3 个答案:

答案 0 :(得分:1)

你可以添加一个永远不会改变的函数参数:

def recur(completeString, string ) :
    if string :
        print string
        recur(completeString, string[:-1])
    else :
         print "Nothing left from '{}'".format(completeString)

recur("hello", "hello")

这将输出:

hello
hell
hel
he
h
Nothing left from 'hello'

答案 1 :(得分:1)

保持递归函数的参数初始值的一种方法是使用附加的关键字参数。通常将此参数赋予默认值None,因此函数的调用者不需要初始化此参数,但是当函数以递归方式调用自身时,它会在需要时进行适当设置。

例如:

def is_substring(sub, string, oldsub=None):
    if sub == "":
        return True
    if string == "":
        return False

    if oldsub is None:
        oldsub = sub

    if sub[0] == string[0]:
        return is_substring(sub[1:], string[1:], oldsub)
    else:
        return is_substring(oldsub, string[1:], oldsub)

保留值的另一种方法是通过在包装函数中定义递归函数来创建closure,如下所示:

def is_substring(sub, string):
    oldsub = sub
    def is_substringR(sub, string):
        if sub == "":
            return True
        if string == "":
            return False

        if oldsub is None:
            oldsub = sub

        if sub[0] == string[0]:
            return is_substringR(sub[1:], string[1:])
        else:
            return is_substringR(oldsub, string[1:])

    return is_substringR(sub, string)        

此函数实现与早期版本相同的算法。而且我很确定这是您尝试使用代码实现的算法。不幸的是,这种算法没有正确找到子串。

所以这里是 正常工作的递归is_substring,但它不需要保留旧的参数值。

def is_substring(sub, string):
    if sub == "":
        return True
    if string == "":
        return False

    if string.startswith(sub):
        return True
    else:
        return is_substring(sub, string[1:])

# some tests

data = (
    ('misip', 'mississippi'),
    ('tle', 'cattle'),
)

for sub, target in data:
    print('{!r} {!r} {}'.format(sub, target, is_substring(sub, target)))

<强>输出

'misip' 'mississippi' False
'tle' 'cattle' True

如果您不想使用.startswith方法,则可以改为使用切片:

def is_substring(sub, string):
    if sub == "":
        return True
    if string == "":
        return False

    if sub == string[:len(sub)]:
        return True
    else:
        return is_substring(sub, string[1:])

正如我在评论中所说,进行子字符串测试的常用方法是使用in运算符,该运算符调用字符串的.__contains__方法。

sub in string

答案 2 :(得分:1)

问题是你的初始通话和后来的通话逻辑略有不同。如果失败,您的初始通话可以简单地前进到字符串中的下一个字符;您之后的电话必须从 sub 的开头重新开始。

我建议使用两个函数:一个包装函数,用于进行第一次比较并保留给定的接口(或者你可以更改它吗?),第二个函数将寻找到最后的连续匹配。

这是一个可能的解决方案,其中插入了跟踪打印语句(并已注释掉)。

def match_all(sub, string):
    # print "ENTER ALL", sub, string
    if sub == "":
        # print "ALL empty sub; success"
        return True
    if string == "":
        # print "ALL empty str; fail"
        return False
    if sub[0] == string[0]:
        # print "ALL head match: recur"
        return match_all(sub[1:],string[1:])
    else:
        # print "ALL head diff: fail"
        return False

def is_substring(sub,string):
    # print "ENTER TOP", sub, string
    if sub == "":
        # print "empty sub; success"
        return True
    if string == "":
        # print "empty str; fail"
        return False
    if sub[0] == string[0]:
        # print "head match: recur"
        if match_all(sub[1:],string[1:]):
            return True
    # print "head diff: recur"
    return is_substring(sub,string[1:])

print is_substring("misip", "mississippi")
# print "------------"
print is_substring("sip", "mississippi")

请注意逻辑更改:main函数查找立即结果,但如果找不到此类解析,仍会继续。支持函数仅查找此字符串位置的立即匹配。

相关问题