【问题标题】:A list of string replacements in PythonPython 中的字符串替换列表
【发布时间】:2010-10-20 08:17:24
【问题描述】:

是否有更短的方法来编写以下代码?

my_string = my_string.replace('A', '1')
my_string = my_string.replace('B', '2')
my_string = my_string.replace('C', '3')
my_string = my_string.replace('D', '4')
my_string = my_string.replace('E', '5')

请注意,我不需要替换那些确切的值;我只是在寻找一种将 5+ 行变成少于 5 行的方法

【问题讨论】:

    标签: python string replace


    【解决方案1】:

    看起来是使用循环的好机会:

    mapping = { 'A':'1', 'B':'2', 'C':'3', 'D':'4', 'E':'5'}
    for k, v in mapping.iteritems():
        my_string = my_string.replace(k, v)
    

    如果您不介意括号的话,一种更快的方法是:

    mapping = [ ('A', '1'), ('B', '2'), ('C', '3'), ('D', '4'), ('E', '5') ]
    for k, v in mapping:
        my_string = my_string.replace(k, v)
    

    【讨论】:

    • 这很奇怪;这就是我写它的方式,因为问题在于从一个字符映射到另一个字符。但实际上,您并没有将字典用作字典;您将其用作元组列表。那么为什么不首先写一个元组列表呢?
    • 当然,元组列表也可以工作(并且更快)。我将编辑答案以包含该选项。
    • 如果你有这个映射 { 'A':'1', '1':'A'} 可能结果不会和预期的一样
    • 定义mapping = zip(list('ABCDE'),range(1,6))的更简洁方式
    • 对于 Python 3,使用 .items() 而不是 .iteritems()
    【解决方案2】:

    您可以轻松地使用 string.maketrans() 创建映射字符串以传递给 str.translate():

    import string
    trans = string.maketrans("ABCDE","12345")
    my_string = my_string.translate(trans)
    

    【讨论】:

    • 这很好,但在多字符模式或替换的情况下不起作用
    • 正确。我从问题中假设它是基于字符的替换。
    • 这实际上是同时替换字符列表的唯一正确方法。例如,如果你做'<>'.replace('<', '>').replace('>','<'),你会得到'<<',但翻译你会得到'><'
    • 在 python 3 中是 str.maketrans("ABCDE", "12345")
    【解决方案3】:

    如果你想得到错误的答案,慢慢地,然后在循环中使用 string.replace。 (虽然在这种模式和替换之间没有重叠的情况下它确实有效。)

    对于可能重叠或主题字符串较长的一般情况,请使用 re.sub:

    import re
    
    def multisub(subs, subject):
        "Simultaneously perform all substitutions on the subject string."
        pattern = '|'.join('(%s)' % re.escape(p) for p, s in subs)
        substs = [s for p, s in subs]
        replace = lambda m: substs[m.lastindex - 1]
        return re.sub(pattern, replace, subject)
    
    >>> multisub([('hi', 'bye'), ('bye', 'hi')], 'hi and bye')
    'bye and hi'
    

    对于 1 字符模式和 1 或 0 字符替换的特殊情况,请使用 string.maketrans。

    【讨论】:

    • +1 表示使用 re.sub 的方法,-1 表示 string.replace 给出了错误的答案,因为不清楚应该对于重叠匹配究竟会发生什么.所以净0 :)
    • str.replace 可以给出一个可以说是错误的答案。对于基于字典的解决方案,请考虑字符串“wow”和翻译表 {'w': 'foo', 'o': 'bar'}。根据 dict 迭代的顺序,您最终可能会得到不同的结果:“fbarbarbarfbarbar”或“foobarfoo”。一个为相同输入提供不同输出的函数可以说是被破坏了。
    • 英里,是的,这就是我的意思。您也可能会在单独的键中遇到重叠,例如“hello”和“hell”。
    【解决方案4】:

    还可以查看str.translate()。它根据您为 Unicode 字符串提供的映射替换字符,否则必须告知用什么替换从 chr(0) 到 chr(255) 的每个字符。

    【讨论】:

      【解决方案5】:
      replaceDict = {'A':'1','B':'2','C':'3','D':'4','E':'5'}
      对于 key,replaceDict.items() 中的替换:
        my_string = my_string.replace(key, 替换)

      【讨论】:

        【解决方案6】:

        我认为它可能会更有效一点:

        mapping = { 'A':'1', 'B':'2', 'C':'3', 'D':'4', 'E':'5'}
        my_string = "".join([mapping[c] if c in mapping else c for c in my_string])
        

        我建议使用“timeit”进行一些基准测试,以“my_string”长度为基础的真实案例。

        【讨论】:

        • 如果您一次有多个替换并且替换并不总是单个字符,这是 IMO 的最佳解决方案。
        【解决方案7】:

        您可以使用 Pandas 在一行中完成。

        import pandas as pd
        
        my_string="A B C test"
        
        my_string =pd.DataFrame([my_string])[0].replace(["A","B","C","D","E"],['1','2','3','4','5'],regex=True)[0]
        
        print(my_string)
        '1 2 3 test'
        

        【讨论】:

          【解决方案8】:

          我这样做的一种方法是使用关联的数组(字典)。下面是我使用正则表达式在 LaTeX 中部署文件时使用的替换示例。

            import re
            def escapeTexString(string): # Returns TeX-friendly string
              rep = { # define desired replacements in this dictionary (mapping)
                   '&': '\\&',
                   '%': '\\%',
                   '#': '\\#',
                   '_': '\\_',
                   '{': '\\{', # REGEX Special
                   '}': '\\}', # REGEX Special
                   '~': '\\char"007E{}', # LaTeX Special
                   '$': '\\$', # REGEX Special
                   '\\': '\\char"005C{}', # REGEX/LaTeX Special
                   '^': '\\char"005E{}', # REGEX/LaTeX Special
                   '"': '\\char"FF02{}'
                  }
              # use these two lines to do the replacement (could be shortened to one line)
              pattern = re.compile("|".join(map(re.escape,rep.keys()))) # Create single pattern object (key to simultaneous replacement)
              new_string = pattern.sub(lambda match: rep[match.group(0)], string)
              return new_string
          

          【讨论】:

          • 请在发帖前阅读其他答案。您的回答与 8 年前 Darius 的回答完全相同。
          猜你喜欢
          • 2019-01-30
          • 2019-02-26
          • 1970-01-01
          • 1970-01-01
          • 2013-06-20
          • 2021-06-17
          • 2021-12-19
          • 1970-01-01
          • 2021-05-22
          相关资源
          最近更新 更多