替换字符串中每个第n个字母

6
我正在编写一个函数,用于替换字符串中的每第n个字母。
def replaceN(str, n):
   for i in range(len(str)):
     n=str[i]
     newStr=str.replace(n, "*")
     return newStr

但是当我执行它时,只有第一个字母被替换成*。我确定有错误,但我看不出来。


replaceN("hello world", 3) 应该返回 *el*o *or*d 吗? - Eric
replaceN("welcome", 3) -> wecoe - trek
7个回答

11

一句话总结:

newstring = ''.join("*" if i % n == 0 else char for i, char in enumerate(string, 1))

扩展:

def replace_n(string, n, first=0):
    letters = (
        # i % n == 0 means this letter should be replaced
        "*" if i % n == 0 else char

        # iterate index/value pairs
        for i, char in enumerate(string, -first)
    )
    return ''.join(letters)
>>> replace_n("hello world", 4)
'*ell* wo*ld'
>>> replace_n("hello world", 4, first=-1)
'hel*o w*orl*'

2

您的代码存在几个问题:

首先,return语句放错了位置。它应该在for循环外面而不是里面。 接下来,在以下片段中:

for i in range(len(str)):
    n=str[i]
    newStr=str.replace(n, "*")

你传递给函数的第二个参数n在每次循环步骤中都被覆盖。因此,如果你的初始字符串是"abcabcabcd",并且你将n=3(一个数字)作为第二个参数传递,那么你的循环所做的是:

n="a"
n="b"
n="c"
...

因此,数值3从未被使用。另外,在您的循环中,只有字符串中最后一个替换被保存:

n="a"
newStr="abcabcabcd".replace("a", "*") --> newStr = "*bc*bc*bcd"
n="b"
newStr="abcabcabcd".replace("b", "*") --> newStr = "a*ca*ca*cd"
...
n="d"
newStr="abcabcabcd".replace("d", "*") --> newStr = "abcabcabc*"

如果你修复了return的位置,并使用一些字符串测试你的函数,它似乎可以正常工作:
In [7]: replaceN("abcabcabc", 3)
Out[7]: 'ab*ab*ab*'

但如果您更加慎重地做出选择:

In [10]: replaceN("abcabcabcd", 3)
Out[10]: 'abcabcabc*'

如果代码失败并且只替换字符串的最后一个字符,则很明显它是无效的。
my_string.replace(my_string[-1], "*")

Eric给出的代码运行良好:

In [16]: ''.join("*" if i % 3 == 0 else char for i, char in enumerate("abcabcabcd"))
Out[16]: '*bc*bc*bc*'

它替换第3、6、9等位置。如果您不想替换位置0,可能需要进行一些调整。


非常感谢您的回答,但我刚开始学习Python,所以您能否简单解释一下呢?谢谢。 - trek
完成。希望现在对您更有帮助。 - Vicent

1

试试这个:

def replaceN(string, n):
    s = ''
    for i in range(len(string)):
        if i%n!=0:
            s += string[i]
        else:
            s += '*'
    return s

3
请说明您的代码如何解决问题或改进了问题中的代码,以及为什么能够做到这一点! - Lukas Körfer

0
您已将返回放在循环内部,因此在第一次迭代之后,它会返回字符串而不替换其余字符串。 应该在循环完全完成后返回字符串。 像这样的代码应该可以解决问题:
def replaceN(str, n):
    for i in range(len(str)):
        n=str[i]
        newStr=str.replace(n, "*")
    return newStr

这是错误的,不起作用。n参数未用于指示字符串中的位置,并且在给定循环步骤中对原始字符串所做的更改会在下一步中丢失。此函数具有与mystring.replace(mystring[-1], "*")相同的效果。 - Vicent

0

另一个选项是使用re:

import re
def repl(matchobj):
    return re.sub('.$','*',matchobj.group(0))
def replaceN(str, n):
    return re.sub('.'*n,repl,str)

然而,这需要额外的库。如果您已经导入了这个库,那么这可能是一种简写方法。


0

我喜欢Eric的回答,但你在评论中指出第一个字母不应该被替换。那么您可以像这样调整代码:

''.join("*" if i % n == 0 else char for i, char in enumerate(string, 1))
                                             the difference is here  ^

def replaceN(s, n):
    return ''.join(
      '*' if not i%n else char for i, char in enumerate(s, 1))

>>> replaceN('welcome', 3)
'we*co*e'

0

通过每次重新定义字符串的简单方法:

def replaceN(string, n):
    for i in range(n, len(string), n):
        string = string[:i-1] + "*" + string[i:]
    return string


In [1]: replaceN("abcabcabc", 3)
Out[1]: ab*ab*ab*
In [2]: replaceN("abcd abcd abcd", 4)
Out[2]: abcd*abcd*abcd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接