6

我正在编写一个函数来替换字符串中的每个第 n 个字母

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

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

4

7 回答 7

10

单线:

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*'
于 2012-12-02T11:31:52.110 回答
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 也被替换,则可能需要进行一些调整。

于 2012-12-02T12:06:47.523 回答
2

尝试这个:

def replaceN(string, n):
    s = ''
    for i in range(len(string)):
        if i%n!=0:
            s += string[i]
        else:
            s += '*'
    return s
于 2017-08-01T07:37:40.323 回答
0

另一种选择,使用 re:

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

但是,这需要额外的库。如果您已经导入了这个库,这可能是一种速记方法。

于 2012-12-02T11:45:06.343 回答
0

您已将 return 放入循环中,因此在第一次迭代后,它会返回字符串,而不会替换字符串的其余部分。循环完全完成后,应返回字符串。像这样的东西应该工作:

def replaceN(str, n):
    for i in range(len(str)):
        n=str[i]
        newStr=str.replace(n, "*")
    return newStr
于 2012-12-02T11:29:11.803 回答
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
于 2012-12-02T12:17:29.553 回答
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'
于 2012-12-02T12:07:21.417 回答