re.subn的一种简单方法,它也可以接受一个函数而不是替换字符串:
import re
from random import randint
def select(m):
choices = m.group(1).split('|')
return choices[randint(0, len(choices)-1)]
def spinner(s):
r = re.compile('{([^{}]*)}')
while True:
s, n = r.subn(select, s)
if n == 0: break
return s.strip()
它只是替换它遇到的所有最深的选择,然后迭代直到没有选择。subn
返回一个元组,其中包含结果以及进行了多少次替换,便于检测处理结束。
如果您只想坚持使用随机选择器,我的版本select()
可以被 Bobince 替换,它使用并且更优雅。random.choice()
如果你想构建一个选择树,你可以扩展上面的函数,但是你需要全局变量来跟踪你的位置,所以将函数移动到一个类中是有意义的。这只是一个提示,我不会发展这个想法,因为它不是真正的原始问题。
最后请注意,r.subn(select, s, re.U)
如果您需要 unicode 字符串,则应使用 ( s = u"{...}"
)
例子:
>>> s = "{{Hello|Hi|Hey} {world|earth} | {Goodbye|farewell} {noobs|n3wbz|n00blets}}"
>>> print spinner(s)
'farewell n3wbz'
编辑:替换sub
为subn
以避免无限循环(感谢 Bobince 指出)并提高效率,并替换{([^{}]+)}
为{([^{}]*)}
提取空大括号。这应该使它对格式错误的模式更加健壮。
对于喜欢尽可能多地放在一条线上的人(我个人不鼓励):
def spin(s):
while True:
s, n = re.subn('{([^{}]*)}',
lambda m: random.choice(m.group(1).split("|")),
s)
if n == 0: break
return s.strip()