簡體   English   中英

Python 3.3:函數的遞歸版本

[英]Python 3.3: Recursive version of a function

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) 的遞歸版本時遇到問題。 有任何想法嗎?

非遞歸解決方案:

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] )或遇到基本情況並且函數完成。

例子

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? 

試試這個代碼,它相當於問題中發布的代碼,但以遞歸方式編寫:

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:]創建額外的中間字符串。 它也是尾遞歸算法的一個例子,它密切反映了迭代解決方案的結構。

接受的答案最初的編寫方式似乎過於復雜。 我已經提交了一個編輯,希望能解決這個問題。 但是當我意識到這一點時,我已經寫了下面的答案和解釋。 保留它,以防解釋對某人有用:

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' 的開頭檢測到 False 條件。我寫的第一種方式有一個錯誤它,未能將 '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 計算。 如果失敗,則答案為 False。 否則,使用除第一個字符以外的所有字符進行遞歸。

  4. "repr(s)" 是一種讓 "s" 與其周圍的引號一起打印的簡單方法。

  5. “optionalNotString”:True/False 情況下所需的答案字符串僅因“not”的存在/不存在而不同。 所以使用“if .. else ..”表達式來控制'not'是否包含在格式化輸出中。 不需要時,替換空字符串 ''。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM