首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >python的php的strtr

python的php的strtr
EN

Stack Overflow用户
提问于 2012-06-07 19:45:41
回答 5查看 3.3K关注 0票数 9

php有strtr函数:

代码语言:javascript
复制
strtr('aa-bb-cc', array('aa' => 'bbz', 'bb' => 'x', 'cc' => 'y'));
# bbz-x-y

它用相应的值替换字符串中的字典键,并且(重要的)不替换已经被替换的字符串。用python编写同样的代码是一次天真的尝试:

代码语言:javascript
复制
def strtr(strng, replace):
    for s, r in replace.items():
        strng = strng.replace(s, r)
    return strng

strtr('aa-bb-cc', {'aa': 'bbz', 'bb': 'x', 'cc': 'y'})

返回我们不想要的xz-x-y (bb再次被替换)。如何更改上面的函数,使其行为与php对应的函数一样?

(如果可能的话,我更喜欢没有正则表达式的答案)。

Upd:这里有一些很好的答案。我对它们进行了计时,发现对于短字符串,Gumbo的版本似乎是最快的,对于长字符串,优胜者是re解决方案:

代码语言:javascript
复制
# 'aa-bb-cc'
0.0258 strtr_thg
0.0274 strtr_gumbo
0.0447 strtr_kojiro
0.0701 strtr_aix

# 'aa-bb-cc'*10
0.1474 strtr_aix
0.2261 strtr_thg
0.2366 strtr_gumbo
0.3226 strtr_kojiro

我自己的版本(略有优化的Gumbo版本):

代码语言:javascript
复制
def strtr(strng, replace):
    buf, i = [], 0
    while i < len(strng):
        for s, r in replace.items():
            if strng[i:len(s)+i] == s:
                buf.append(r)
                i += len(s)
                break
        else:
            buf.append(strng[i])
            i += 1
    return ''.join(buf)

完整的代码和时间:https://gist.github.com/2889181

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-06-07 20:10:54

下面是一个简单的算法:

使用索引逐字符遍历原始字符串,并检查每个索引中是否有一个搜索字符串等于从当前索引开始的字符串。如果找到匹配项,则在缓冲区中推送替换项,并按匹配字符串的长度继续索引。如果未找到匹配项,则按1继续索引。最后,将缓冲区中的字符串连接为单个字符串。

代码语言:javascript
复制
def strtr(strng, replace):
    buffer = []
    i, n = 0, len(strng)
    while i < n:
        match = False
        for s, r in replace.items():
            if strng[i:len(s)+i] == s:
                buffer.append(r)
                i = i + len(s)
                match = True
                break
        if not match:
            buffer.append(strng[i])
            i = i + 1
    return ''.join(buffer)
票数 3
EN

Stack Overflow用户

发布于 2012-06-07 20:40:10

下面使用正则表达式来完成此操作:

代码语言:javascript
复制
import re

def strtr(s, repl):
  pattern = '|'.join(map(re.escape, sorted(repl, key=len, reverse=True)))
  return re.sub(pattern, lambda m: repl[m.group()], s)

print(strtr('aa-bb-cc', {'aa': 'bbz', 'bb': 'x', 'cc': 'y'}))

与PHP的版本一样,它优先考虑更长的匹配。

票数 7
EN

Stack Overflow用户

发布于 2012-06-07 20:51:38

代码语言:javascript
复制
def strtr(strng, replace):
    if replace and strng:
        s, r = replace.popitem()
        return r.join(strtr(subs, dict(replace)) for subs in strng.split(s))
    return strng

j=strtr('aa-bb-cc', {'aa': 'bbz', 'bb': 'x', 'cc': 'y'})
assert j=='bbz-x-y', j
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10931150

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档