2016-03-07 29 views
8

我有一个字符串,其中一个字符('@')需要被一个或多个字符“按顺序”和“周期性”列表中的字符替换。 所以,比如我有在Python中“定期”替换字符串中的字符的最佳方式是什么?

'[email protected]@@[email protected]@[email protected]@@[email protected]@[email protected]'

,并希望

'ab1cde23fghi1jk2lmno312p3qrs1tuvwxy2z'

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

的问题是,在这个例子中有更多@字符串 比我有替代品。

这是我的尝试:

result = '' 
replace_chars = ['1', '2', '3'] 
string = '[email protected]@@[email protected]@[email protected]@@[email protected]@[email protected]' 

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

print(result) 

但这仅仅的作品当然,如果有不超过三个@原字符串中否则我得到IndexError

编辑:谢谢你的答案!

+2

使用'replace_chars [i%replace_chars.length]'。那么你只能做到索引中的“模”。例如3个字符,你做'1%3 - > 1','2%3 - > 2','3%3 - > 0','4%3 - > 1'等等...... –

+4

加'i在'i + = 1'下面的%= 3' –

回答

10

您的代码可以通过添加行i = i%len(replace_chars)作为您的if子句的最后一行来解决。这样,您将按照替换字符列表的长度从i的分区中取出剩余部分。

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

>>> from itertools import cycle 
>>> s = '[email protected]@@[email protected]@[email protected]@@[email protected]@[email protected]' 
>>> replace_chars = ['1', '2', '3'] 
>>> 
>>> replacer = cycle(replace_chars) 
>>> ''.join([next(replacer) if c == '@' else c for c in s]) 
'ab1cde23fghi1jk2lmno312p3qrs1tuvwxy2z' 

对于你的字符串s每个字符c,我们从replacer产生下一个替换字符如果字符是一个'@',否则它只是给你原来的角色。

有关为什么我使用列表理解而不是生成器表达式的解释,请参阅this

6

发电机很有趣。

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

with gen() as g: 
    s = '[email protected]@@[email protected]@[email protected]@@[email protected]@[email protected]' 
    s = ''.join(next(g) if c == '@' else c for c in s) 

正如PM2Ring所建议的,这在功能上与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 
+2

你的'gen'基本上就是'itertools.cycle'所做的。 –

+1

对。通常,即使标准软件包中有一个有用的工具,我也喜欢为了便于阅读而编写本地等价物。假设是一个人不知道上述工具。通常情况下,它只是给你一个更好的理解。如果你想使用'itertools.cycle',一定要这样做。 – Goodies

+0

@ PM2Ring'cycle'也保存给定迭代中的元素,因为迭代器可能是一个可以耗尽的迭代器 - 但是如果'replace_chars'保证是一个列表,@Goodies生成器应该工作正常。 – timgeb

1

你也可以让你的索引逻辑,一旦你使用取模,使用列表补偿使用itertools.count跟踪你在哪里:

from itertools import count 

cn, ln = count(), len(replace_chars) 

print("".join([replace_chars[next(cn) % ln] if c == "@" else c for c in string])) 

ab1cde23fghi1jk2lmno312p3qrs1tuvwxy2z 
相关问题