簡體   English   中英

使用遞歸在字符串中顯示多個子字符串索引

[英]Displaying multiple substring indices within a string by using recursion

def subStringMatchExact(target, key):

    if (target.find(key) == -1):
        return []
    else:
        foundStringAt = [target.find(key)]
        target = target[foundStringAt[0] + len(key):]
        return foundStringAt + subStringMatchExact(target, key)

string = subStringMatchExact("your code works with wrongly correlated coefficients which incorporates more costs", "co") 

print(string)

當前輸出錯誤:

[5, 22, 9, 19, 14]

我在上一個遞歸步驟中總結子字符串的長度時遇到了麻煩。 像列表的第二元件應當是29而不是22作為len(previousSubstring) + len(key) - 1 + len(currentSubstring)

有什么想法來改進我的代碼和/或修復我的錯誤嗎?

快捷的方式

您不必實施自己的解決方案,它已經完成了! 使用re模塊中的finditer函數:

>>> import re
>>> s = 'your code works with wrongly correlated coefficients which incorporates more costs'
>>> matches = re.finditer('co', s)
>>> positions = [ match.start() for match in matches ]
>>> positions
[5, 29, 40, 61, 77]

你自己的方式

如果你想自己實現(使用遞歸),你可以利用str.find函數的額外參數。 讓我們看看有什么help(str.find)說的:

S.find(sub [,start [,end]]) -> int

    Return the lowest index in S where substring sub is found,
    such that sub is contained within s[start:end].  Optional
    arguments start and end are interpreted as in slice notation.

    Return -1 on failure.

還有一個名為start的額外參數告訴str.find哪里開始搜索子字符串。 這正是我們所需要的!

因此,修改您的實現,我們可以獲得一個簡單,快速和美觀的解決方案:

def substring_match_exact(pattern, string, where_should_I_start=0):
    # Save the result in a variable to avoid doing the same thing twice
    pos = string.find(pattern, where_should_I_start)
    if pos == -1:
        # Not found!
        return []
    # No need for an else statement
    return [pos] + substring_match_exact(pattern, string, pos + len(key))

這里的遞歸是什么?

  • 您首先在位置0開始搜索字符串中的子字符串。
  • 如果未找到子字符串,則返回空列表[]
  • 如果找到子字符串,它將返回[pos]加上子字符串將出現在 pos + len(key)位置開始的字符串中的所有位置。

使用我們全新的功能

>>> s = 'your code works with wrongly correlated coefficients which incorporates more costs'
>>> substring_match_exact('co', s)
[5, 29, 40, 61, 77]

目前,您的代碼正在嘗試在縮短的字符串中找到co的索引,而不是原始字符串。 因此,雖然[5, 22, 9, 19, 14]可能看起來不正確,但腳本正在完成您告訴它要做的事情。 通過包含偏移量,如下面的腳本,此代碼可以工作。

def subStringMatchExact(target, key, offset=0): # note the addition of offset

    if (target.find(key) == -1):
        return []
    else:
        foundStringAt = target.find(key)
        target = target[foundStringAt + len(key):]
        foundStringAt += offset # added
        return [foundStringAt] + subStringMatchExact(target, key, foundStringAt + len(key))
        # added foundStringAt + len(key) part

string = subStringMatchExact("your code works with wrongly correlated coefficients which incorporates more costs", "co") 
# no need to call w/ 0 since offset defaults to 0 if no offset is given

print(string)

我要補充一點,使foundStringAt一個list從一開始就只有一個值打交道時不是偉大實踐,因為你每增加一些開銷[0]索引查找。 相反,既然你想要一個list返回類型,你應該把它放在return語句的[]中(如我的代碼所示)。

您總是在相應的子字符串中添加位置。

return foundStringAt + subStringMatchExact(target, key)

,函數調用的結果與“new”字符串target有關,該target與“舊”字符串target不同,因為它是使用target = target[foundStringAt[0] + len(key):]重新定義的。

所以你應該將這個值恰好添加到函數調用結果中:

    foundStringAt = target.find(key)
    offset = foundStringAt + len(key)
    target = target[offset:]
    return [foundStringAt] + [i + offset for i in subStringMatchExact(target, key)]

應該做的伎倆(未經測試)。

除了練習外,我不打算使用遞歸。

解決問題:

我在上一個遞歸步驟中總結子字符串的長度時遇到了麻煩。

你真正想要“求和”的是已經搜索過的字符串的數量。 將此函數作為參數傳遞給函數(第一次調用使用0),將刪除的字符串數量( foundStringAt[0] + len(key):當前)添加到遞歸調用的輸入值。

作為格式化(並使事物與其名稱更好地對應),您可能會發現讓foundStringAt直接存儲結果(而不是那個1元素列表)更foundStringAt ,並將列表包裝作為表達式與遞歸調用。

暫無
暫無

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

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