Saya perlu mengganti beberapa karakter sebagai berikut: &
➔ \&
, #
➔ \#
, ...
Saya memberi kode sebagai berikut, tetapi saya kira harus ada cara yang lebih baik. Ada petunjuk?
strs = strs.replace('&', '\&')
strs = strs.replace('#', '\#')
...
Saya perlu mengganti beberapa karakter sebagai berikut: &
➔ \&
, #
➔ \#
, ...
Saya memberi kode sebagai berikut, tetapi saya kira harus ada cara yang lebih baik. Ada petunjuk?
strs = strs.replace('&', '\&')
strs = strs.replace('#', '\#')
...
Jawaban:
Saya menghitung semua metode dalam jawaban saat ini bersama dengan satu tambahan.
Dengan string masukan dari abc&def#ghi
dan mengganti & -> \ & dan # -> \ #, cara tercepat adalah mengikat rantai pengganti seperti ini:text.replace('&', '\&').replace('#', '\#')
.
Pengaturan waktu untuk setiap fungsi:
Berikut fungsinya:
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'\#')
Jangka waktu seperti ini:
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')"
Berikut kode yang mirip untuk melakukan hal yang sama tetapi dengan lebih banyak karakter untuk melarikan diri (\ `* _ {}> # + -.! $):
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'\$')
Inilah hasil untuk string input yang sama abc&def#ghi
:
Dan dengan string input yang lebih panjang ( ## *Something* and [another] thing in a longer sentence with {more} things to replace$
):
Menambahkan beberapa varian:
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)
Dengan input yang lebih pendek:
Dengan input yang lebih panjang:
Jadi saya akan gunakan ba
untuk keterbacaan dan kecepatan.
Diminta oleh haccks di komentar, satu perbedaan antara ab
dan ba
adalah if c in text:
cek. Mari kita uji mereka terhadap dua varian lagi:
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)
Waktu dalam μs per loop pada Python 2.7.14 dan 3.6.3, dan pada mesin yang berbeda dari set sebelumnya, jadi tidak dapat dibandingkan secara langsung.
╭────────────╥──────┬───────────────┬──────┬──────────────────╮
│ 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 │
└────────────╨──────┴───────────────┴──────┴──────────────────┘
Kita dapat menyimpulkan bahwa:
Orang-orang dengan cek hingga 4x lebih cepat daripada mereka yang tidak memeriksa
ab_with_check
sedikit memimpin pada Python 3, tetapi ba
(dengan cek) memiliki keunggulan yang lebih besar pada Python 2
Namun, pelajaran terbesar di sini adalah Python 3 hingga 3x lebih cepat dari Python 2 ! Tidak ada perbedaan besar antara yang paling lambat di Python 3 dan tercepat di Python 2!
if c in text:
perlu masuk ba
?
1.45 usec per loop
, dan tanpa: 5.3 usec per loop
, panjang tali, dengan: 4.38 usec per loop
dan tanpa: 7.03 usec per loop
. (Perhatikan ini tidak langsung sebanding dengan hasil di atas, karena ini adalah mesin yang berbeda dll.)
replace
dipanggil hanya ketika c
ditemukan text
dalam kasus ba
sementara dipanggil dalam setiap iterasi di ab
.
>>> string="abc&def#ghi"
>>> for ch in ['&','#']:
... if ch in string:
... string=string.replace(ch,"\\"+ch)
...
>>> print string
abc\&def\#ghi
string=string.replace(ch,"\\"+ch)
? Tidak string.replace(ch,"\\"+ch)
cukup?
Cukup rantai replace
fungsi seperti ini
strs = "abc&def#ghi"
print strs.replace('&', '\&').replace('#', '\#')
# abc\&def\#ghi
Jika penggantiannya akan lebih banyak, Anda dapat melakukan ini dengan cara yang umum ini
strs, replacements = "abc&def#ghi", {"&": "\&", "#": "\#"}
print "".join([replacements.get(c, c) for c in strs])
# abc\&def\#ghi
Berikut adalah metode python3 menggunakan str.translate
dan str.maketrans
:
s = "abc&def#ghi"
print(s.translate(str.maketrans({'&': '\&', '#': '\#'})))
String yang dicetak adalah abc\&def\#ghi
.
.translate()
tampaknya lebih lambat dari tiga dirantai .replace()
(menggunakan CPython 3.6.4).
replace()
diri saya sendiri, tetapi saya menambahkan jawaban ini demi kelengkapan.
'\#'
valid tidak harus itu r'\#'
atau '\\#'
? Mungkin masalah pemformatan blok kode.
Apakah Anda akan selalu menambahkan backslash? Jika ya, coba
import re
rx = re.compile('([&#])')
# ^^ fill in the characters here.
strs = rx.sub('\\\\\\1', strs)
Ini mungkin bukan metode yang paling efisien tapi saya pikir ini yang paling mudah.
r'\\\1'
Terlambat ke pesta, tetapi saya kehilangan banyak waktu dengan masalah ini sampai saya menemukan jawaban saya.
Pendek dan manis, translate
lebih unggulreplace
. Jika Anda lebih tertarik pada fungsi dari waktu ke waktu optimasi, jangan gunakanreplace
.
Juga gunakan translate
jika Anda tidak tahu apakah set karakter yang akan diganti tumpang tindih set karakter yang digunakan untuk mengganti.
Inti masalah:
Menggunakan replace
Anda akan secara naif mengharapkan cuplikan "1234".replace("1", "2").replace("2", "3").replace("3", "4")
untuk kembali "2344"
, tetapi sebenarnya akan kembali "4444"
.
Terjemahan tampaknya melakukan apa yang awalnya diinginkan OP.
Anda dapat mempertimbangkan menulis fungsi pelarian umum:
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
Dengan cara ini Anda dapat membuat fungsi Anda dapat dikonfigurasi dengan daftar karakter yang harus diloloskan.
FYI, ini sedikit atau tidak berguna untuk OP tetapi mungkin berguna untuk pembaca lain (tolong jangan downvote, saya tahu ini).
Sebagai latihan yang agak konyol tapi menarik, ingin melihat apakah saya bisa menggunakan pemrograman fungsional python untuk menggantikan beberapa karakter. Saya cukup yakin ini TIDAK mengalahkan hanya memanggil ganti () dua kali. Dan jika kinerja adalah masalah, Anda dapat dengan mudah mengalahkan ini dalam karat, C, julia, perl, java, javascript dan bahkan mungkin awk. Ia menggunakan paket 'pembantu' eksternal yang disebut pytoolz , dipercepat melalui cython ( cytoolz, ini adalah paket 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),))))))
Saya bahkan tidak akan menjelaskan ini karena tidak ada yang mau repot-repot menggunakan ini untuk menyelesaikan banyak penggantian. Namun demikian, saya merasa agak berhasil dalam melakukan ini dan berpikir itu mungkin menginspirasi pembaca lain atau memenangkan kontes kode kebingungan.
Menggunakan mengurangi yang tersedia di python2.7 dan python3. * Anda dapat dengan mudah mengganti substring mutiple dengan cara yang bersih dan pythonic.
# 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"
Dalam python2.7 Anda tidak perlu mengimpor mengurangi tetapi dalam python3. * Anda harus mengimpornya dari modul functools.
Mungkin loop sederhana untuk mengganti karakter:
a = '&#'
to_replace = ['&', '#']
for char in to_replace:
a = a.replace(char, "\\"+char)
print(a)
>>> \&\#