在Python中"定期"替换字符串中字符的最佳方法是什么?

Fir*_*lda 8 python replace python-3.x

我有一个字符串,其中一个字符('@')需要被"按顺序"和"定期"的一个或多个字符列表中的字符替换.所以我举个例子

'ab@cde@@fghi@jk@lmno@@@p@qrs@tuvwxy@z'

并希望

'ab1cde23fghi1jk2lmno312p3qrs1tuvwxy2z'

对于 replace_chars = ['1', '2', '3']

问题是在这个例子中,字符串中的@比我有替换者的更多.

这是我的尝试:

result = ''
replace_chars = ['1', '2', '3']
string = 'ab@cde@@fghi@jk@lmno@@@p@qrs@tuvwxy@z'

i = 0
for char in string:
    if char == '@':
        result += replace_chars[i]
        i += 1
    else:
        result += char

print(result)
Run Code Online (Sandbox Code Playgroud)

但是这只有在原始字符串中不超过3个@的情况下才有效,否则我会得到IndexError.

编辑:谢谢你的回答!

tim*_*geb 10

您可以通过将该行添加i = i%len(replace_chars)if子句的最后一行来修复您的代码.通过这种方式,您将从i替换字符列表的长度中取出剩余部分.

较短的解决方案是使用定期吐出替换字符的生成器.

>>> from itertools import cycle
>>> s = 'ab@cde@@fghi@jk@lmno@@@p@qrs@tuvwxy@z'
>>> replace_chars = ['1', '2', '3']
>>>
>>> replacer = cycle(replace_chars)
>>> ''.join([next(replacer) if c == '@' else c for c in s])
'ab1cde23fghi1jk2lmno312p3qrs1tuvwxy2z'
Run Code Online (Sandbox Code Playgroud)

对于c字符串中的每个字符,如果字符是a s,我们将从replacer生成器中获取下一个替换字符'@',否则它只会为您提供原始字符.

为了解释为什么我使用列表推导而不是生成器表达式,请阅读此内容.


Goo*_*ies 6

发电机很有趣.

def gen():
    replace_chars = ['1', '2', '3']
    while True:
        for rc in replace_chars:
            yield rc

with gen() as g:
    s = 'ab@cde@@fghi@jk@lmno@@@p@qrs@tuvwxy@z'
    s = ''.join(next(g) if c == '@' else c for c in s)
Run Code Online (Sandbox Code Playgroud)

正如PM 2Ring建议的那样,这在功能上是相同的itertools.cycle.不同之处在于,itertools.cycle它将在内存中保存一份额外的副本,这可能不是必需的.

itertools.cycle 资源:

def cycle(iterable):
    saved = []
    for element in iterable:
        yield element
        saved.append(element)
    while saved:
        for element in saved:
              yield element
Run Code Online (Sandbox Code Playgroud)

  • 你的`gen`本质上是`itertools.cycle`的作用. (2认同)
  • 当然!当我想循环遍历list/tuple/string时,我自己做了同样的事情.有时,它*值得重新发明<s>循环</ s>轮.:) (2认同)