Replacing two characters
I timed all the methods in the current answers along with one extra.
With an input string of abc&def#ghi and replacing & -> \& and # -> \#, the fastest way was to chain together the replacements like this: text.replace('&', '\&').replace('#', '\#').
Timings for each function:
- a) 1000000 loops, best of 3: 1.47 ฮผs per loop
- b) 1000000 loops, best of 3: 1.51 ฮผs per loop
- c) 100000 loops, best of 3: 12.3 ฮผs per loop
- d) 100000 loops, best of 3: 12 ฮผs per loop
- e) 100000 loops, best of 3: 3.27 ฮผs per loop
- f) 1000000 loops, best of 3: 0.817 ฮผs per loop
- g) 100000 loops, best of 3: 3.64 ฮผs per loop
- h) 1000000 loops, best of 3: 0.927 ฮผs per loop
- i) 1000000 loops, best of 3: 0.814 ฮผs per loop
Here are the functions:
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'\#')
Timed like this:
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')"
Replacing 17 characters
Here's similar code to do the same but with more characters to escape (\`*_{}>#+-.!$):
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('
')
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('
')
Here's the results for the same input string abc&def#ghi:
- a) 100000 loops, best of 3: 6.72 ฮผs per loop
- b) 100000 loops, best of 3: 2.64 ฮผs per loop
- c) 100000 loops, best of 3: 11.9 ฮผs per loop
- d) 100000 loops, best of 3: 4.92 ฮผs per loop
- e) 100000 loops, best of 3: 2.96 ฮผs per loop
- f) 100000 loops, best of 3: 4.29 ฮผs per loop
- g) 100000 loops, best of 3: 4.68 ฮผs per loop
- h) 100000 loops, best of 3: 4.73 ฮผs per loop
- i) 100000 loops, best of 3: 4.24 ฮผs per loop
And with a longer input string (## *Something* and [another] thing in a longer sentence with {more} things to replace$):
- a) 100000 loops, best of 3: 7.59 ฮผs per loop
- b) 100000 loops, best of 3: 6.54 ฮผs per loop
- c) 100000 loops, best of 3: 16.9 ฮผs per loop
- d) 100000 loops, best of 3: 7.29 ฮผs per loop
- e) 100000 loops, best of 3: 12.2 ฮผs per loop
- f) 100000 loops, best of 3: 5.38 ฮผs per loop
- g) 10000 loops, best of 3: 21.7 ฮผs per loop
- h) 100000 loops, best of 3: 5.7 ฮผs per loop
- i) 100000 loops, best of 3: 5.13 ฮผs per loop
Adding a couple of variants:
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)
With the shorter input:
- ab) 100000 loops, best of 3: 7.05 ฮผs per loop
- ba) 100000 loops, best of 3: 2.4 ฮผs per loop
With the longer input:
- ab) 100000 loops, best of 3: 7.71 ฮผs per loop
- ba) 100000 loops, best of 3: 6.08 ฮผs per loop
So I'm going to use ba for readability and speed.
Addendum
Prompted by haccks in the comments, one difference between ab and ba is the if c in text: check. Let's test them against two more variants:
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)
Times in ฮผs per loop on Python 2.7.14 and 3.6.3, and on a different machine from the earlier set, so cannot be compared directly.
โญโโโโโโโโโโโโโฅโโโโโโโฌโโโโโโโโโโโโโโโโฌโโโโโโโฌโโโโโโโโโโโโโโโโโโโฎ
โ 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 โ
โโโโโโโโโโโโโโจโโโโโโโดโโโโโโโโโโโโโโโโดโโโโโโโดโโโโโโโโโโโโโโโโโโโ
We can conclude that:
Those with the check are up to 4x faster than those without the check
ab_with_checkis slightly in the lead on Python 3, butba(with check) has a greater lead on Python 2However, the biggest lesson here is Python 3 is up to 3x faster than Python 2! There's not a huge difference between the slowest on Python 3 and fastest on Python 2!
Replacing two characters
I timed all the methods in the current answers along with one extra.
With an input string of abc&def#ghi and replacing & -> \& and # -> \#, the fastest way was to chain together the replacements like this: text.replace('&', '\&').replace('#', '\#').
Timings for each function:
- a) 1000000 loops, best of 3: 1.47 ฮผs per loop
- b) 1000000 loops, best of 3: 1.51 ฮผs per loop
- c) 100000 loops, best of 3: 12.3 ฮผs per loop
- d) 100000 loops, best of 3: 12 ฮผs per loop
- e) 100000 loops, best of 3: 3.27 ฮผs per loop
- f) 1000000 loops, best of 3: 0.817 ฮผs per loop
- g) 100000 loops, best of 3: 3.64 ฮผs per loop
- h) 1000000 loops, best of 3: 0.927 ฮผs per loop
- i) 1000000 loops, best of 3: 0.814 ฮผs per loop
Here are the functions:
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'\#')
Timed like this:
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')"
Replacing 17 characters
Here's similar code to do the same but with more characters to escape (\`*_{}>#+-.!$):
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('
')
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('
')
Here's the results for the same input string abc&def#ghi:
- a) 100000 loops, best of 3: 6.72 ฮผs per loop
- b) 100000 loops, best of 3: 2.64 ฮผs per loop
- c) 100000 loops, best of 3: 11.9 ฮผs per loop
- d) 100000 loops, best of 3: 4.92 ฮผs per loop
- e) 100000 loops, best of 3: 2.96 ฮผs per loop
- f) 100000 loops, best of 3: 4.29 ฮผs per loop
- g) 100000 loops, best of 3: 4.68 ฮผs per loop
- h) 100000 loops, best of 3: 4.73 ฮผs per loop
- i) 100000 loops, best of 3: 4.24 ฮผs per loop
And with a longer input string (## *Something* and [another] thing in a longer sentence with {more} things to replace$):
- a) 100000 loops, best of 3: 7.59 ฮผs per loop
- b) 100000 loops, best of 3: 6.54 ฮผs per loop
- c) 100000 loops, best of 3: 16.9 ฮผs per loop
- d) 100000 loops, best of 3: 7.29 ฮผs per loop
- e) 100000 loops, best of 3: 12.2 ฮผs per loop
- f) 100000 loops, best of 3: 5.38 ฮผs per loop
- g) 10000 loops, best of 3: 21.7 ฮผs per loop
- h) 100000 loops, best of 3: 5.7 ฮผs per loop
- i) 100000 loops, best of 3: 5.13 ฮผs per loop
Adding a couple of variants:
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)
With the shorter input:
- ab) 100000 loops, best of 3: 7.05 ฮผs per loop
- ba) 100000 loops, best of 3: 2.4 ฮผs per loop
With the longer input:
- ab) 100000 loops, best of 3: 7.71 ฮผs per loop
- ba) 100000 loops, best of 3: 6.08 ฮผs per loop
So I'm going to use ba for readability and speed.
Addendum
Prompted by haccks in the comments, one difference between ab and ba is the if c in text: check. Let's test them against two more variants:
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)
Times in ฮผs per loop on Python 2.7.14 and 3.6.3, and on a different machine from the earlier set, so cannot be compared directly.
โญโโโโโโโโโโโโโฅโโโโโโโฌโโโโโโโโโโโโโโโโฌโโโโโโโฌโโโโโโโโโโโโโโโโโโโฎ
โ 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 โ
โโโโโโโโโโโโโโจโโโโโโโดโโโโโโโโโโโโโโโโดโโโโโโโดโโโโโโโโโโโโโโโโโโโ
We can conclude that:
Those with the check are up to 4x faster than those without the check
ab_with_checkis slightly in the lead on Python 3, butba(with check) has a greater lead on Python 2However, the biggest lesson here is Python 3 is up to 3x faster than Python 2! There's not a huge difference between the slowest on Python 3 and fastest on Python 2!
Here is a python3 method using str.translate and str.maketrans:
s = "abc&def#ghi"
print(s.translate(str.maketrans({'&': '\&', '#': '\#'})))
The printed string is abc\&def\#ghi.
Is there an easier way to replace multiple different things at once
how to replace multiple characters in one go with the .replace() function?
Which is the better way to include multiple '.replace()' ?
Python: How can I replace one specific character on a string while leaving the rest of the string as it was?
Videos
Hello, I would like to replace a certain letter in a string with a '*' (don't ask lol)
The problem is it will only either do it for the lower case letters or upper case letters.
Is there a way to get the function to replace both upper and lower case letters or am I going to need to use the function twice?
Thanks