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

时间:2016-03-07 21:28:06

标签: python python-3.x replace

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

'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)

但这仅在原始字符串中的@不超过3时才有效,否则我会得到 IndexError

编辑:感谢您的回答!

4 个答案:

答案 0 :(得分:10)

您的代码可以通过添加行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' 除以剩余替换字符列表的长度。

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

c

对于字符串s中的每个字符replacer,如果字符为'@',我们会从$total = 0; $result = $conn->query("SELECT count(points) as total FROM scores WHERE player_id='$player' ORDER by points ASC"); $row = $result->fetch_array(); if($row['total'] >= 10) { $result = $conn->query("SELECT sum(points) as SumPoints FROM scores WHERE player_id='$player' ORDER by points ASC LIMIT 5"); $row = $result->fetch_array(); $total = $row['SumPoints']; } 生成器获取下一个替换字符,否则它只会给您原来的角色。

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

答案 1 :(得分:6)

发电机很有趣。

globals [listOfInitialVals]
turtles-own [val]
to init-turtle
  set val random-float 1 ;just for illustration
  set listOfTurtleVals (lput val listOfInitialVals)
end

正如PM 2Ring建议的那样,这在功能上与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) 相同。区别在于itertools.cycle将在内存中保存一份额外的副本,这可能没有必要。

itertools.cycle来源:

itertools.cycle

答案 2 :(得分: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

答案 3 :(得分:0)

我认为最好不要逐个字符地进行迭代,尤其是对于没有@的冗长部分的长字符串。

from itertools import cycle, chain

s = 'ab@cde@@fghi@jk@lmno@@@p@qrs@tuvwxy@z'
replace_chars = ['1', '2', '3']
result = ''.join(chain.from_iterable(zip(s.split('@'), cycle(replace_chars))))[:-1]

我不知道如何有效杀死最后一个字符[:-1]