簡體   English   中英

嘗試使用 python 中的遞歸在字符串中最后一次出現 substring

[英]Trying to get the last occurrence of a substring in string using recursion in python

我正在嘗試獲取以字符串 subString 開頭和結尾的消息的最長 substring 的長度

這是結果應該是什么樣子的表格:帶有示例和輸出的表格

這是我到目前為止得到的代碼:

dist = 0
def strDist(message, subString):
    global dist
    if message.find(subString) == -1:
        return dist
    else:
        dist += message.find(subString) + len(subString)
    return strDist(dist*' ' + message[dist:], subString)

這是測試儀代碼:

from recursion import *
allPassed = True

def strDistMain():
    global allPassed    
    testCases = [(1, 'cat dog cat dog cat', 'cat', 19),
                 (2, 'cat dog cat dog ca', 'cat', 11),
                 (3, 'at dog cat dog cat', 'cat', 11),
                 (4, 'dog cat dog', 'cat', 3),
                 (5, 'dog dog', 'cat', 0),
                 (6, 'cat', 'cat', 3),
                 (7, 'ca', 'cat', 0),
                 (8, 'c', 'cat', 0),
                 (9, '', 'cat', 0),
                 (10, 'cat', '', 3),
                 (11, '', '', 0)
                 ]
    
    for num, message, mark, expected in testCases:
        result = strDist(message, mark)
        if result != expected:
            print(f'String Distance Test {num} Failed. Expected {expected} got {result}')
            allPassed = False

def main():     
    strDistMain()
    if allPassed:
        print('All tests passed')

    
main()  

該代碼根本不起作用,我不確定是什么問題。 這是迄今為止我得到的 output:

String Distance Test 1 Failed. Expected 19 got 33
String Distance Test 2 Failed. Expected 11 got 36
String Distance Test 3 Failed. Expected 11 got 46
String Distance Test 4 Failed. Expected 3 got 53
String Distance Test 5 Failed. Expected 0 got 53
String Distance Test 6 Failed. Expected 3 got 56
String Distance Test 7 Failed. Expected 0 got 56
String Distance Test 8 Failed. Expected 0 got 56
String Distance Test 9 Failed. Expected 0 got 56
builtins.RecursionError: maximum recursion depth exceeded while calling a Python object

首先,你不需要使用遞歸,你可以這樣做:

def strDist(message, mark):
    if message.find(mark) == -1:
        return 0
    return message.rfind(mark) - message.find(mark) + len(mark)

但是,如果你出於某種原因想用遞歸來做,你可以這樣做:

def strDist(message, mark):
    index = message.find(mark)
    if index == -1:
        return 0
    return recursive_last(message, mark) - index + len(mark)

def recursive_last(message, mark):
    index = message.find(mark)
    if index == -1:
        return -1
    return max(index, recursive_last(message[index + len(mark):], mark) + index)
    

第一個 function 獲取第一個出現的索引,並調用遞歸,找到第一個 ocurrency,將其從字符串中刪除,然后重試。

您的strDist function 是否會收斂到基本情況並不明顯。 在遞歸 function 中使用global幾乎總是會使調試和推理變得更加困難; 很有可能dist在某個時候會以您不期望的值結束,這就是導致無限遞歸的原因。

在遞歸 function 中使用find (這是一個迭代函數)無論如何都會達到目的,因為正如所指出的那樣,如果您要使用find找到最左邊的出現,您也可以使用rfind找到最右邊的出現, 然后你就完成了,根本不需要做任何遞歸。

一個純粹的遞歸(也是低效的)解決方案看起來更像:

def str_dist(message, substr):
    if len(message) < len(substr):
        return -1
    if message.startswith(substr) and message.endswith(substr):
        return len(message)
    return max(str_dist(message[1:], substr), str_dist(message[:-1], substr))

上面的 function 是純粹遞歸的,因為它不會在給定的 function 調用中對message進行任何迭代(請注意, startswithendswith都是對substr的迭代;如果你真的想的話,你也可以編寫它們的遞歸版本)和它通過了你所有的測試。

它有兩個基本情況:

  • 如果messagesubstr短,則沒有有效的答案。 (需要某種形式的“太小”基本情況來防止對空字符串進行無限遞歸——如果你想讓這個檢查更簡單,你可以將空字符串作為基本情況。)
  • 如果message本身滿足以substr開頭和結尾的條件,則答案是len(message)

否則,這是message[1:]message[:-1]的最佳答案。

暫無
暫無

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

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