繁体   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