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

2024-12-12 08:41:00
admin
原创
76
摘要:问题描述:我需要替换一些字符,如下所示:&➔ &,#➔ #,...我的代码如下,但我想应该有更好的方法。有什么提示吗?strs = strs.replace('&', '&') strs = strs.replace('#', '#') ... 解决方案 1:替换两个字符我对当...

问题描述:

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

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

strs = strs.replace('&', '&')
strs = strs.replace('#', '#')
...

解决方案 1:

替换两个字符

我对当前答案中的所有方法以及一个额外的方法进行了计时。

输入字符串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'\\', text)


RX = re.compile('([&#])')
def d(text):
    text = RX.sub(r'\\', 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'\\', text)


RX = re.compile('([\\`*_{}[]()>#+-.!$])')
def d(text):
    text = RX.sub(r'\\', 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 次中最佳:每次循环 5.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 次中最佳:每次循环 7.71 μs

  • ba) 100000 次循环,3 次中最佳:每次循环 6.08 μs

所以我将使用它ba来提高可读性和速度。

附录

受评论中 hacks 的提示,ab和之间的一个区别baif 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 上最快的之间并没有太大的区别!

解决方案 2:

这是一个使用str.translateand 的python3 方法str.maketrans

s = "abc&def#ghi"
print(s.translate(str.maketrans({'&': '&', '#': '#'})))

打印的字符串是abc&def#ghi

解决方案 3:

>>> string="abc&def#ghi"
>>> for ch in ['&','#']:
...   if ch in string:
...      string=string.replace(ch,"\\\"+ch)
...
>>> print string
abc&def#ghi

解决方案 4:

replace只需像这样链接函数即可

strs = "abc&def#ghi"
print strs.replace('&', '&').replace('#', '#')
# abc&def#ghi

如果替换的数量较多,你可以用这种通用方法进行操作

strs, replacements = "abc&def#ghi", {"&": "&", "#": "#"}
print "".join([replacements.get(c, c) for c in strs])
# abc&def#ghi

解决方案 5:

虽然迟到了,但是我在这个问题上浪费了很多时间才找到答案。

简而言之,translate优于replace。如果您对功能随时间优化更感兴趣,请不要使用replace

translate如果您不知道要替换的字符集是否与用于替换的字符集重叠,也可以使用。

例如:

使用时,replace您会天真地期望代码片段"1234".replace("1", "2").replace("2", "3").replace("3", "4")返回"2344",但事实上它会返回"4444"

翻译似乎实现了 OP 最初的愿望。

解决方案 6:

你总是要添加反斜杠吗?如果是的话,试试

import re
rx = re.compile('([&#])')
#                  ^^ fill in the characters here.
strs = rx.sub('\\\\\\1', strs)

这可能不是最有效的方法,但我认为它是最简单的。

解决方案 7:

对于 Python 3.8 及更高版本,可以使用赋值表达式

[text := text.replace(s, f"\\{s}") for s in "&#" if s in text];

虽然我不太确定这是否被视为PEP 572中描述的赋值表达式的“适当使用” ,但看起来很干净,读起来也相当好(在我看来)。如果您在 REPL 中运行此代码,末尾的分号会抑制输出。

如果您还想要所有中间字符串,这将是“合适的”。例如,(删除所有小写元音):

text = "Lorem ipsum dolor sit amet"
intermediates = [text := text.replace(i, "") for i in "aeiou" if i in text]

['Lorem ipsum dolor sit met',
 'Lorm ipsum dolor sit mt',
 'Lorm psum dolor st mt',
 'Lrm psum dlr st mt',
 'Lrm psm dlr st mt']

从好的方面来看,它确实似乎(出乎意料?)比接受的答案中的某些更快的方法更快,并且似乎在增加字符串长度和增加替换次数的情况下表现良好。

比较

上述比较的代码如下。我使用随机字符串来简化我的生活,并且要替换的字符是从字符串本身随机选择的。(注意:我在这里使用 ipython 的 %timeit magic,因此在 ipython/jupyter 中运行它)。

import random, string

def make_txt(length):
    "makes a random string of a given length"
    return "".join(random.choices(string.printable, k=length))

def get_substring(s, num):
    "gets a substring"
    return "".join(random.choices(s, k=num))

def a(text, replace): # one of the better performing approaches from the accepted answer
    for i in replace:
        if i in text:
             text = text.replace(i, "")

def b(text, replace):
    _ = (text := text.replace(i, "") for i in replace if i in text) 


def compare(strlen, replace_length):
    "use ipython / jupyter for the %timeit functionality"

    times_a, times_b = [], []

    for i in range(*strlen):
        el = make_txt(i)
        et = get_substring(el, replace_length)

        res_a = %timeit -n 1000 -o a(el, et) # ipython magic

        el = make_txt(i)
        et = get_substring(el, replace_length)
        
        res_b = %timeit -n 1000 -o b(el, et) # ipython magic

        times_a.append(res_a.average * 1e6)
        times_b.append(res_b.average * 1e6)
        
    return times_a, times_b

#----run
t2 = compare((2*2, 1000, 50), 2)
t10 = compare((2*10, 1000, 50), 10)

解决方案 8:

您可以考虑编写一个通用的转义函数:

def mk_esc(esc_chars):
    return lambda s: ''.join(['\\' + c if c in esc_chars else c for c in s])

>>> esc = mk_esc('&#')
>>> print esc('Learn & be #1')
Learn & be #1

这样,您就可以使用需要转义的字符列表来配置您的函数。

解决方案 9:

仅供参考,这对 OP 来说没什么用,但对其他读者可能会有用(请不要投反对票,我知道这一点)。

作为一个有点荒谬但有趣的练习,我想看看我是否可以使用 python 函数式编程来替换多个字符。我很确定这不会比只调用 replace() 两次更好。如果性能是一个问题,你可以轻松地在 rust、C、julia、perl、java、javascript 甚至 awk 中解决这个问题。它使用一个名为pytoolz的外部“帮助程序”包,通过 cython 加速(cytoolz,它是一个 pypi 包)。

from cytoolz.functoolz import compose
from cytoolz.itertoolz import chain,sliding_window
from itertools import starmap,imap,ifilter
from operator import itemgetter,contains
text='&hello#hi&yo&'
char_index_iter=compose(partial(imap, itemgetter(0)), partial(ifilter, compose(partial(contains, '#&'), itemgetter(1))), enumerate)
print '\\'.join(imap(text.__getitem__, starmap(slice, sliding_window(2, chain((0,), char_index_iter(text), (len(text),))))))

我甚至不会解释这一点,因为没有人会费心使用它来完成多次替换。尽管如此,我还是觉得这样做很有成就感,并认为这可能会激励其他读者或赢得代码混淆比赛。

解决方案 10:

这个怎么样?

def replace_all(dict, str):
    for key in dict:
        str = str.replace(key, dict[key])
    return str

然后

print(replace_all({"&":"&", "#":"#"}, "&#"))

输出

&#

类似于答案

解决方案 11:

使用 python2.7 和 python3.* 中提供的 reduce,您可以轻松地以干净且符合 Python 风格的方式替换多个子字符串。

# Lets define a helper method to make it easy to use
def replacer(text, replacements):
    return reduce(
        lambda text, ptuple: text.replace(ptuple[0], ptuple[1]), 
        replacements, text
    )

if __name__ == '__main__':
    uncleaned_str = "abc&def#ghi"
    cleaned_str = replacer(uncleaned_str, [("&","&"),("#","#")])
    print(cleaned_str) # "abc&def#ghi"

在 python2.7 中您不必导入 reduce,但在 python3.* 中您必须从 functools 模块导入它。

解决方案 12:

使用正则表达式的高级方法

import re
text = "hello ,world!"
replaces = {"hello": "hi", "world":" 2020", "!":"."}
regex = re.sub("|".join(replaces.keys()), lambda match: replaces[match.string[match.start():match.end()]], text)
print(regex)

解决方案 13:

>>> a = '&#'
>>> print a.replace('&', r'&')
&#
>>> print a.replace('#', r'#')
&#
>>> 

您想要使用“原始”字符串(用替换字符串前缀“r”表示),因为原始字符串不会特殊处理反斜杠。

解决方案 14:

也许可以用一个简单的循环来替换字符:

a = '&#'

to_replace = ['&', '#']

for char in to_replace:
    a = a.replace(char, "\\\"+char)

print(a)

>>> &#

解决方案 15:

这将帮助那些寻求简单解决方案的人。

def replacemany(our_str, to_be_replaced:tuple, replace_with:str):
    for nextchar in to_be_replaced:
        our_str = our_str.replace(nextchar, replace_with)
    return our_str

os = 'the rain in spain falls mainly on the plain ttttttttt sssssssssss nnnnnnnnnn'
tbr = ('a','t','s','n')
rw = ''

print(replacemany(os,tbr,rw))

输出:

他日我 pi fll mily o 他 pli

解决方案 16:

下面给出了或条件的示例,它将从给定的字符串中删除所有 ' 和 ,。传递任意多个字符,并用 | 分隔。

import re
test = re.sub("('|,)","",str(jsonAtrList))

前:
在此处输入图片描述

后:
在此处输入图片描述

解决方案 17:

使用 .translate() 函数进行多次替换

# Original string
original_string = "12#4526&18##0"

translation_dict = {'&': r'&',
                    '#': r'#'}

# Create a translation table using the dictionary
translation_table = str.maketrans(translation_dict)

# Translate the string
modified_string = original_string.translate(translation_table)

print(modified_string)  # Output: 12#4526&18##0
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   984  
  在项目管理领域,CDCP(Certified Data Center Professional)认证评审是一个至关重要的环节,它不仅验证了项目团队的专业能力,还直接关系到项目的成功与否。在这一评审过程中,沟通技巧的运用至关重要。有效的沟通不仅能够确保信息的准确传递,还能增强团队协作,提升评审效率。本文将深入探讨CDCP...
华为IPD流程   0  
  IPD(Integrated Product Development,集成产品开发)是一种以客户需求为核心、跨部门协同的产品开发模式,旨在通过高效的资源整合和流程优化,提升产品开发的成功率和市场竞争力。在IPD培训课程中,掌握关键成功因素是确保团队能够有效实施这一模式的核心。以下将从五个关键成功因素展开讨论,帮助企业和...
IPD项目流程图   0  
  华为IPD(Integrated Product Development,集成产品开发)流程是华为公司在其全球化进程中逐步构建和完善的一套高效产品开发管理体系。这一流程不仅帮助华为在技术创新和产品交付上实现了质的飞跃,还为其在全球市场中赢得了显著的竞争优势。IPD的核心在于通过跨部门协作、阶段性评审和市场需求驱动,确保...
华为IPD   0  
  华为作为全球领先的通信技术解决方案提供商,其成功的背后离不开一套成熟的管理体系——集成产品开发(IPD)。IPD不仅是一种产品开发流程,更是一种系统化的管理思想,它通过跨职能团队的协作、阶段评审机制和市场需求驱动的开发模式,帮助华为在全球市场中脱颖而出。从最初的国内市场到如今的全球化布局,华为的IPD体系在多个领域展现...
IPD管理流程   0  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用