Python 3.3:函数的递归版本

时间:2012-11-30 00:48:33

标签: python recursion python-3.x

def abc(s):
    filter = [i for i in s.lower() if i in 'abcdefghijklmnopqrstuvwxyz']
    for i in range(len(filter) - 1):
        if filter[i] > filter[i+1]:
            return print(s, "is not abcdearian")
    return print(s,  "is abcdearian")


while True:
    try:
        s = input("String? ")
abc(s)

我在制作abc(s)的递归版本时遇到了麻烦。有什么想法吗?

3 个答案:

答案 0 :(得分:3)

非递归解决方案:

def issorted(L):
    return all(x <= y for x, y in zip(L, L[1:]))

要制作递归函数,您应该找到一种方法将问题拆分为更小和/或更简单的子问题,这些问题可以通过相同的方式解决:

#!/usr/bin/env python3
from string import ascii_lowercase

def abcdearian(s):
    return issorted_recursive([c for c in s.lower() if c in ascii_lowercase])

def issorted_recursive(L):
    return L[0] <= L[1] and issorted_recursive(L[1:]) if len(L) > 1 else True

这里issorted_recursive()是一个递归函数。基本情况为len(L) <= 1(具有零个或一个元素的列表始终排序,因此在这种情况下返回True)。在递归情况(len(L) > 1)中,如果第一个项目处于排序顺序(L并且列表的其余部分,则列表L[0] <= L[1]被视为已排序(L[1:])也已排序。每次函数接收越来越小的输入,直到找到乱序元素(L[0] > L[1])或遇到基本情况并且函数结束。

Example

while True:
    s = input("String? ")
    if not s:
        break
    print("{} is {}abcdearian".format(s, "" if abcdearian(s) else "not "))

输入

    abc
    bac

输出

String? abc is abcdearian
String? bac is not abcdearian
String? 

答案 1 :(得分:0)

尝试使用此代码,它相当于问题中发布的代码,但是以递归方式编写:

from string import ascii_lowercase

def abc(s):
    f = [c for c in s.lower() if c in ascii_lowercase]
    if aux(f, 0):
        return s + " is abcdearian"
    else:
        return s + " is not abcdearian"

def aux(s, i):
    if i >= len(s)-1:
        return True
    elif s[i] > s[i+1]:
        return False
    else:
        return aux(s, i+1)

像这样使用:

while True:
    s = input("String? ")
    if not s:
        break
    print(abc(s))

请注意,我将问题分成两部分:首先,“main”函数abc()负责过滤字符串,使用正确的初始值调用aux过程并返回结果字符串。结束(或者:你可以返回一个布尔值,在别处创建结果字符串。)

真正的工作是在helper aux函数中完成的,如果字符串中所有连续字符对的“abcdearian”条件为真,则递归遍历字符串检查。 aux遍历字符串的方式是有效的(抛开我们使用递归的事实),因为它永远不会使用s[1:]创建额外的中间字符串。它也是tail-recursive算法的一个例子,它与迭代解决方案的结构密切相关。

答案 2 :(得分:0)

最初编写接受的答案的方式似乎过于复杂。我已经提交了一个希望修复它的编辑。但是当我意识到这一点时,我已经写了下面的答案和解释。保留它,以防解释对某人有用:

def abc(s):
    filtered = [i for i in s.lower() if i in 'abcdefghijklmnopqrstuvwxyz']
    optionalNotString = ('' if _abc(filtered) else ' not')
    print( '{0} is{1} abcdearian'.format( repr(s), optionalNotString ) )

# Recursively process the "rest" (remainder) of the string.
# At each step, examine the first two characters.
def _abc(rest):
    if len(rest) < 2:
        # We've successfully compared all successive pairs, so return True.
        return True
    if (rest[0] > rest[1]):
        return False
    return _abc(rest[1:])

在使用中(最重要的情况是测试,包括太短的字符串,并在字符串'acb'的末尾检测到错误状态,以及字符串'bac'的开头。我有一个错误第一个我编写它的方式,未能将'bac'视为False!):

abc( '' )
abc( 'a' )
abc( 'ac' )
abc( 'abc' )
abc( 'acb' )
abc( 'bac' )

输出:

'' is abcdearian
'a' is abcdearian
'ac' is abcdearian
'abc' is abcdearian
'acb' is not abcdearian
'bac' is not abcdearian

说明:

  1. 过滤只需要进行一次,所以在主“abc”函数中进行,而不是在递归的“_abc”函数中进行。

  2. 在每个步骤中,算法需要查看两个相邻的字符。在每次调用“_abc”时,这些都是前两个字符。

  3. “_ abc”需要处理两种情况:

    • 案例1:字符串太短而无法进行比较。例如。 ''或'a'。这样的字符串满足abcderian标准,因此返回True。

    • 案例2:字符串至少有两个字符。执行前两个的abcderian计算。如果失败,答案是假的。否则,使用除第一个字符以外的所有字符递归。

  4. “repr(s)”是一种简单的方法,可以使用周围的引号来打印“s”。

  5. “optionalNotString”:True / False情况下的所需答案字符串仅因“not”的存在/不存在而不同。因此,使用“if .. else ..”表达式来控制格式化输出中是否包含“not”。如果不需要,请替换空字符串''。