Python-替换字符串中多个字符的最佳方法?

发布于 2021-02-02 23:12:14

我需要替换一些字符,如下所示:&➔ \&,#➔ \#,…

我编码如下,但是我想应该有一些更好的方法。有什么提示吗?

strs = strs.replace('&', '\&')
strs = strs.replace('#', '\#')
...
关注者
0
被浏览
65
1 个回答
  • 面试哥
    面试哥 2021-02-02
    为面试而生,有面试问题,就找面试哥。

    替换两个字符

    我给当前答案中的所有方法加上了一个额外的时间。

    使用输入字符串abc&def#ghi并替换&-> \&#-> \#,最快的方法是将替换链接在一起,如下所示:text.replace('&', '\&').replace('#', '\#')

    每个功能的时间:

    • a)1000000次循环,每个循环最好为3:1.47 s
    • b)1000000个循环,每个循环的最佳时间为3:1.51μs
    • c)100000个循环,每个循环最好为3:12.3μs
    • d)100000个循环,每个循环最好为3:12μs
    • e)100000个循环,每个循环最好为3:3.27μs
    • f)1000000次循环,最好为3:每个循环0.817μs
    • g)100000个循环,每个循环中最好为3:3.64μs
    • h)1000000次循环,每循环最好3:0.927μs
    • i)1000000次循环,最佳3:每个循环0.814μs

    功能如下:

    def a(text):
        chars = "&#"
        for c in chars:
            text = text.replace(c, "\\" + c)
    
    
    def b(text):
        for ch in ['&','#']:
            if ch in text:
                text = text.replace(ch,"\\"+ch)
    
    
    import re
    def c(text):
        rx = re.compile('([&#])')
        text = rx.sub(r'\\\1', text)
    
    
    RX = re.compile('([&#])')
    def d(text):
        text = RX.sub(r'\\\1', text)
    
    
    def mk_esc(esc_chars):
        return lambda s: ''.join(['\\' + c if c in esc_chars else c for c in s])
    esc = mk_esc('&#')
    def e(text):
        esc(text)
    
    
    def f(text):
        text = text.replace('&', '\&').replace('#', '\#')
    
    
    def g(text):
        replacements = {"&": "\&", "#": "\#"}
        text = "".join([replacements.get(c, c) for c in text])
    
    
    def h(text):
        text = text.replace('&', r'\&')
        text = text.replace('#', r'\#')
    
    
    def i(text):
        text = text.replace('&', r'\&').replace('#', r'\#')
    

    像这样计时:

    python -mtimeit -s"import time_functions" "time_functions.a('abc&def#ghi')"
    python -mtimeit -s"import time_functions" "time_functions.b('abc&def#ghi')"
    python -mtimeit -s"import time_functions" "time_functions.c('abc&def#ghi')"
    python -mtimeit -s"import time_functions" "time_functions.d('abc&def#ghi')"
    python -mtimeit -s"import time_functions" "time_functions.e('abc&def#ghi')"
    python -mtimeit -s"import time_functions" "time_functions.f('abc&def#ghi')"
    python -mtimeit -s"import time_functions" "time_functions.g('abc&def#ghi')"
    python -mtimeit -s"import time_functions" "time_functions.h('abc&def#ghi')"
    python -mtimeit -s"import time_functions" "time_functions.i('abc&def#ghi')"
    

    替换17个字符

    下面是类似的代码,它们可以执行相同的操作,但是要转义更多的字符(`* _ {}>#+-。!$):

    def a(text):
        chars = "\\`*_{}[]()>#+-.!$"
        for c in chars:
            text = text.replace(c, "\\" + c)
    
    
    def b(text):
        for ch in ['\\','`','*','_','{','}','[',']','(',')','>','#','+','-','.','!','$','\'']:
            if ch in text:
                text = text.replace(ch,"\\"+ch)
    
    
    import re
    def c(text):
        rx = re.compile('([&#])')
        text = rx.sub(r'\\\1', text)
    
    
    RX = re.compile('([\\`*_{}[]()>#+-.!$])')
    def d(text):
        text = RX.sub(r'\\\1', text)
    
    
    def mk_esc(esc_chars):
        return lambda s: ''.join(['\\' + c if c in esc_chars else c for c in s])
    esc = mk_esc('\\`*_{}[]()>#+-.!$')
    def e(text):
        esc(text)
    
    
    def f(text):
        text = text.replace('\\', '\\\\').replace('`', '\`').replace('*', '\*').replace('_', '\_').replace('{', '\{').replace('}', '\}').replace('[', '\[').replace(']', '\]').replace('(', '\(').replace(')', '\)').replace('>', '\>').replace('#', '\#').replace('+', '\+').replace('-', '\-').replace('.', '\.').replace('!', '\!').replace('$', '\$')
    
    
    def g(text):
        replacements = {
            "\\": "\\\\",
            "`": "\`",
            "*": "\*",
            "_": "\_",
            "{": "\{",
            "}": "\}",
            "[": "\[",
            "]": "\]",
            "(": "\(",
            ")": "\)",
            ">": "\>",
            "#": "\#",
            "+": "\+",
            "-": "\-",
            ".": "\.",
            "!": "\!",
            "$": "\$",
        }
        text = "".join([replacements.get(c, c) for c in text])
    
    
    def h(text):
        text = text.replace('\\', r'\\')
        text = text.replace('`', r'\`')
        text = text.replace('*', r'\*')
        text = text.replace('_', r'\_')
        text = text.replace('{', r'\{')
        text = text.replace('}', r'\}')
        text = text.replace('[', r'\[')
        text = text.replace(']', r'\]')
        text = text.replace('(', r'\(')
        text = text.replace(')', r'\)')
        text = text.replace('>', r'\>')
        text = text.replace('#', r'\#')
        text = text.replace('+', r'\+')
        text = text.replace('-', r'\-')
        text = text.replace('.', r'\.')
        text = text.replace('!', r'\!')
        text = text.replace('$', r'\$')
    
    
    def i(text):
        text = text.replace('\\', r'\\').replace('`', r'\`').replace('*', r'\*').replace('_', r'\_').replace('{', r'\{').replace('}', r'\}').replace('[', r'\[').replace(']', r'\]').replace('(', r'\(').replace(')', r'\)').replace('>', r'\>').replace('#', r'\#').replace('+', r'\+').replace('-', r'\-').replace('.', r'\.').replace('!', r'\!').replace('$', r'\$')
    

    这是相同输入字符串的结果abc&def#ghi:

    • a)100000次循环,每循环3:6.72μs最佳
    • b)100000个循环,每个循环最好为3:2.64μs
    • c)100000个循环,每个循环最好3:11.9μs
    • d)100000个循环,每个循环的最佳时间为3:4.92μs
    • e)100000个循环,每个循环中最好为3:2.96μs
    • f)100000个循环,每个循环最好为3:4.29μs
    • g)100000个循环,每个循环最好为3:4.68μs
    • h)100000次循环,每循环3:4.73μs最佳
    • i)100000个循环,每个循环最好为3:4.24μs

    并使用更长的输入字符串(## Something and [another] thing in a longer sentence with {more} things to replace$):

    • a)100000个循环,每个循环的最佳时间为3:7.59μs
    • b)100000个循环,每个循环最好3:6.54μs
    • c)100000个循环,每个循环最好3:16.9μs
    • d)100000个循环,每个循环的最佳时间为3:7.29μs
    • e)100000个循环,最佳3:每个循环12.2μs
    • f)100000个循环,每个循环最好为3:3.38μs
    • g)10000个循环,每个循环最好3:21.7μs
    • h)100000个循环,最佳3:每个循环5.7μs
    • i)100000个循环,每个循环最好为3:5.13 s

    添加几个变体:

    def ab(text):
        for ch in ['\\','`','*','_','{','}','[',']','(',')','>','#','+','-','.','!','$','\'']:
            text = text.replace(ch,"\\"+ch)
    
    
    def ba(text):
        chars = "\\`*_{}[]()>#+-.!$"
        for c in chars:
            if c in text:
                text = text.replace(c, "\\" + c)
    

    输入较短时:

    • ab)100000个循环,每个循环中最好为3:7.05μs
    • ba)100000个循环,最佳3:每个循环2.4μs

    输入较长时:

    • ab)100000个循环,每个循环最好为3:3.71μs
    • ba)100000个循环,最佳3:每个循环6.08μs

    因此,我将使用ba其可读性和速度。

    附录

    注释中出现提示,提示ab和之间的区别ba是if c in text:检查。让我们针对另外两个变体进行测试:

    def ab_with_check(text):
        for ch in ['\\','`','*','_','{','}','[',']','(',')','>','#','+','-','.','!','$','\'']:
            if ch in text:
                text = text.replace(ch,"\\"+ch)
    
    def ba_without_check(text):
        chars = "\\`*_{}[]()>#+-.!$"
        for c in chars:
            text = text.replace(c, "\\" + c)
    

    在Python 2.7.14和3.6.3上,以及与早期版本不同的计算机上,每个循环的时间(以μs为单位),因此无法直接进行比较。

    ╭────────────╥──────┬───────────────┬──────┬──────────────────╮
    │ Py, input  ║  ab  │ ab_with_check │  ba  │ ba_without_check │
    ╞════════════╬══════╪═══════════════╪══════╪══════════════════╡
    │ Py2, short ║ 8.81 │    4.22       │ 3.45 │    8.01          │
    │ Py3, short ║ 5.54 │    1.34       │ 1.46 │    5.34          │
    ├────────────╫──────┼───────────────┼──────┼──────────────────┤
    │ Py2, long  ║ 9.3  │    7.15       │ 6.85 │    8.55          │
    │ Py3, long  ║ 7.43 │    4.38       │ 4.41 │    7.02          │
    └────────────╨──────┴───────────────┴──────┴──────────────────┘
    

    我们可以得出以下结论:

    有支票的人的速度比没有支票的人快4倍

    ab_with_check在Python 3上稍有领先,但是ba(带检查)在Python 2上有更大的领先

    但是,这里最大的教训是Python 3比Python 2快3倍!Python 3上最慢的速度与Python 2上最快的速度之间没有太大的区别!



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看