Saya menghitung semua metode dalam jawaban saat ini bersama dengan satu tambahan.
Dengan string masukan dari abc&def#ghidan mengganti & -> \ & dan # -> \ #, cara tercepat adalah mengikat rantai pengganti seperti ini:text.replace('&', '\&').replace('#', '\#') .
Pengaturan waktu untuk setiap fungsi:
a) 1000000 loop, terbaik 3: 1,47 μs per loop
b) 10.00000 loop, terbaik 3: 1,51 μs per loop
c) 100000 loop, terbaik 3: 12,3 μs per loop
d) 100000 loop, terbaik 3: 12 μs per loop
e) 100000 loop, terbaik 3: 3,27 μs per loop
f) 10.00000 loop, terbaik 3: 0,817 μs per loop
g) 100000 loop, terbaik 3: 3,64 μs per loop
h) 10.00000 loop, terbaik 3: 0,927 μs per loop
i) 10.00000 loop, terbaik 3: 0,814 μs per loop
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):returnlambda 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'\#')
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):returnlambda 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:
a) 100000 loop, terbaik dari 3: 6,72 μs per loop
b) 100000 loop, terbaik 3: 2,64 μs per loop
c) 100000 loop, terbaik 3: 11,9 μs per loop
d) 100000 loop, terbaik 3: 4,92 μs per loop
e) 100000 loop, terbaik 3: 2,96 μs per loop
f) 100000 loop, terbaik 3: 4,29 μs per loop
g) 100000 loop, terbaik 3: 4,68 μs per loop
h) 100000 loop, terbaik 3: 4,73 μs per loop
i) 100000 loop, terbaik 3: 4,24 μs per loop
Dan dengan string input yang lebih panjang ( ## *Something* and [another] thing in a longer sentence with {more} things to replace$):
a) 100000 loop, terbaik 3: 7,59 μs per loop
b) 100000 loop, terbaik 3: 6,54 μs per loop
c) 100000 loop, terbaik 3: 16,9 μs per loop
d) 100000 loop, terbaik 3: 7,29 μs per loop
e) 100000 loop, terbaik 3: 12,2 μs per loop
f) 100000 loop, terbaik 3: 5,38 μs per loop
g) 10.000 loop, terbaik 3: 21,7 μs per loop
h) 100000 loop, terbaik 3: 5,7 μs per loop
i) 100000 loop, terbaik 3: 5,13 μs per loop
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:
ab) 100000 loop, terbaik 3: 7,05 μs per loop
ba) 100000 loop, terbaik 3: 2,4 μs per loop
Dengan input yang lebih panjang:
ab) 100000 loop, terbaik 3: 7,71 μs per loop
ba) 100000 loop, terbaik 3: 6,08 μs per loop
Jadi saya akan gunakan bauntuk keterbacaan dan kecepatan.
Tambahan
Diminta oleh haccks di komentar, satu perbedaan antara abdan baadalah 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_checksedikit 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!
@haccks Tidak perlu, tapi 2-3x lebih cepat dengannya. Tali pendek, dengan: 1.45 usec per loop, dan tanpa: 5.3 usec per loop, panjang tali, dengan: 4.38 usec per loopdan tanpa: 7.03 usec per loop. (Perhatikan ini tidak langsung sebanding dengan hasil di atas, karena ini adalah mesin yang berbeda dll.)
Hugo
1
@Hugo; Saya pikir perbedaan waktu ini adalah karena replacedipanggil hanya ketika cditemukan textdalam kasus basementara dipanggil dalam setiap iterasi di ab.
pukul
2
@haccks Terima kasih, saya telah memperbarui jawaban saya dengan pengaturan waktu lebih lanjut: menambahkan cek lebih baik untuk keduanya, tetapi pelajaran terbesar adalah Python 3 hingga 3x lebih cepat!
Hugo
73
>>> string="abc&def#ghi">>>for ch in['&','#']:...if ch in string:... string=string.replace(ch,"\\"+ch)...>>>print string
abc\&def\#ghi
Ini adalah jawaban yang baik, tetapi dalam praktiknya melakukan satu .translate()tampaknya lebih lambat dari tiga dirantai .replace()(menggunakan CPython 3.6.4).
Changaco
@ Changaco Terima kasih atas pengaturan waktunya 👍 Dalam praktiknya saya akan menggunakan replace()diri saya sendiri, tetapi saya menambahkan jawaban ini demi kelengkapan.
tommy.carstensen
Untuk string besar dan banyak penggantian ini harus lebih cepat, meskipun beberapa pengujian akan menyenangkan ...
Graipher
Yah, ini bukan di komputer saya (sama untuk penggantian 2 dan 17).
Graipher
bagaimana '\#'valid tidak harus itu r'\#'atau '\\#'? Mungkin masalah pemformatan blok kode.
parity3
16
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.
Terlambat ke pesta, tetapi saya kehilangan banyak waktu dengan masalah ini sampai saya menemukan jawaban saya.
Pendek dan manis, translatelebih unggulreplace . Jika Anda lebih tertarik pada fungsi dari waktu ke waktu optimasi, jangan gunakanreplace .
Juga gunakan translatejika Anda tidak tahu apakah set karakter yang akan diganti tumpang tindih set karakter yang digunakan untuk mengganti.
Inti masalah:
Menggunakan replaceAnda 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):returnlambda 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 usedef 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.
>>> a ='&#'>>>print a.replace('&', r'\&')
\&#>>>print a.replace('#', r'\#')&\#
>>>
Anda ingin menggunakan string 'mentah' (dilambangkan dengan awalan 'r' string pengganti), karena string mentah tidak memperlakukan backslash secara khusus.
Jawaban:
Mengganti dua karakter
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:
Jangka waktu seperti ini:
Mengganti 17 karakter
Berikut kode yang mirip untuk melakukan hal yang sama tetapi dengan lebih banyak karakter untuk melarikan diri (\ `* _ {}> # + -.! $):
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:
Dengan input yang lebih pendek:
Dengan input yang lebih panjang:
Jadi saya akan gunakan
ba
untuk keterbacaan dan kecepatan.Tambahan
Diminta oleh haccks di komentar, satu perbedaan antara
ab
danba
adalahif c in text:
cek. Mari kita uji mereka terhadap dua varian lagi: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.
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, tetapiba
(dengan cek) memiliki keunggulan yang lebih besar pada Python 2Namun, 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!
sumber
if c in text:
perlu masukba
?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 ketikac
ditemukantext
dalam kasusba
sementara dipanggil dalam setiap iterasi diab
.sumber
string=string.replace(ch,"\\"+ch)
? Tidakstring.replace(ch,"\\"+ch)
cukup?Cukup rantai
replace
fungsi seperti iniJika penggantiannya akan lebih banyak, Anda dapat melakukan ini dengan cara yang umum ini
sumber
Berikut adalah metode python3 menggunakan
str.translate
danstr.maketrans
:String yang dicetak adalah
abc\&def\#ghi
.sumber
.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 itur'\#'
atau'\\#'
? Mungkin masalah pemformatan blok kode.Apakah Anda akan selalu menambahkan backslash? Jika ya, coba
Ini mungkin bukan metode yang paling efisien tapi saya pikir ini yang paling mudah.
sumber
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.
sumber
Anda dapat mempertimbangkan menulis fungsi pelarian umum:
Dengan cara ini Anda dapat membuat fungsi Anda dapat dikonfigurasi dengan daftar karakter yang harus diloloskan.
sumber
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 ).
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.
sumber
Menggunakan mengurangi yang tersedia di python2.7 dan python3. * Anda dapat dengan mudah mengganti substring mutiple dengan cara yang bersih dan pythonic.
Dalam python2.7 Anda tidak perlu mengimpor mengurangi tetapi dalam python3. * Anda harus mengimpornya dari modul functools.
sumber
Mungkin loop sederhana untuk mengganti karakter:
sumber
Bagaimana dengan ini?
kemudian
keluaran
mirip dengan jawaban
sumber
Anda ingin menggunakan string 'mentah' (dilambangkan dengan awalan 'r' string pengganti), karena string mentah tidak memperlakukan backslash secara khusus.
sumber