2016-03-07 30 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 
相關問題