Tôi cần phải thay thế một số nhân vật như sau: &
➔ \&
, #
➔ \#
, ...
Tôi đã mã hóa như sau, nhưng tôi đoán nên có một cách tốt hơn. Có gợi ý nào không?
strs = strs.replace('&', '\&')
strs = strs.replace('#', '\#')
...
Tôi cần phải thay thế một số nhân vật như sau: &
➔ \&
, #
➔ \#
, ...
Tôi đã mã hóa như sau, nhưng tôi đoán nên có một cách tốt hơn. Có gợi ý nào không?
strs = strs.replace('&', '\&')
strs = strs.replace('#', '\#')
...
Câu trả lời:
Tôi đã tính thời gian cho tất cả các phương thức trong các câu trả lời hiện tại cùng với một phương pháp bổ sung.
Với chuỗi đầu vào abc&def#ghi
và thay thế & -> \ & và # -> \ #, cách nhanh nhất là xâu chuỗi các thay thế như thế này : text.replace('&', '\&').replace('#', '\#')
.
Thời gian cho từng chức năng:
Dưới đây là các chức năng:
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'\#')
Thời gian như thế này:
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')"
Đây là mã tương tự để làm tương tự nhưng có nhiều ký tự để thoát (\ `* _ {}> # + -.! $):
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'\$')
Đây là kết quả cho cùng một chuỗi đầu vào abc&def#ghi
:
Và với chuỗi đầu vào dài hơn ( ## *Something* and [another] thing in a longer sentence with {more} things to replace$
):
Thêm một vài biến thể:
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)
Với đầu vào ngắn hơn:
Với đầu vào dài hơn:
Vì vậy, tôi sẽ sử dụng ba
cho khả năng đọc và tốc độ.
Được nhắc nhở bởi haccks trong các ý kiến, một sự khác biệt giữa ab
và ba
là if c in text:
kiểm tra. Hãy thử nghiệm chúng với hai biến thể khác:
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)
Thời gian tính bằng per trên mỗi vòng lặp trên Python 2.7.14 và 3.6.3 và trên một máy khác với bộ trước đó, do đó không thể so sánh trực tiếp.
╭────────────╥──────┬───────────────┬──────┬──────────────────╮
│ 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 │
└────────────╨──────┴───────────────┴──────┴──────────────────┘
Chúng ta có thể kết luận rằng:
Những người có séc nhanh hơn gấp 4 lần so với những người không có séc
ab_with_check
hơi dẫn đầu về Python 3, nhưng ba
(có kiểm tra) có lượng khách hàng tiềm năng lớn hơn trên Python 2
Tuy nhiên, bài học lớn nhất ở đây là Python 3 nhanh hơn gấp 3 lần so với Python 2 ! Không có sự khác biệt lớn giữa chậm nhất trên Python 3 và nhanh nhất trên Python 2!
if c in text:
cần thiết trong ba
?
1.45 usec per loop
và không có : 5.3 usec per loop
, Chuỗi dài, có: 4.38 usec per loop
và không có : 7.03 usec per loop
. (Lưu ý những điều này không thể so sánh trực tiếp với kết quả ở trên, vì đó là một máy khác, v.v.)
replace
chỉ được gọi khi c
được tìm thấy text
trong trường hợp ba
trong khi nó được gọi trong mỗi lần lặp trong 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)
? Không string.replace(ch,"\\"+ch)
đủ sao?
Đơn giản chỉ cần chuỗi các replace
chức năng như thế này
strs = "abc&def#ghi"
print strs.replace('&', '\&').replace('#', '\#')
# abc\&def\#ghi
Nếu sự thay thế sẽ có số lượng nhiều hơn, bạn có thể làm điều này theo cách chung này
strs, replacements = "abc&def#ghi", {"&": "\&", "#": "\#"}
print "".join([replacements.get(c, c) for c in strs])
# abc\&def\#ghi
Đây là một phương pháp python3 sử dụng str.translate
và str.maketrans
:
s = "abc&def#ghi"
print(s.translate(str.maketrans({'&': '\&', '#': '\#'})))
Chuỗi in là abc\&def\#ghi
.
.translate()
dường như chậm hơn ba chuỗi .replace()
(sử dụng CPython 3.6.4).
replace()
bản thân mình, nhưng tôi đã thêm câu trả lời này vì mục đích hoàn chỉnh.
'\#'
hợp lệ? không nên r'\#'
hay '\\#'
sao? Có thể là một vấn đề định dạng khối mã có lẽ.
Bạn luôn luôn chuẩn bị một dấu gạch chéo ngược? Nếu vậy, hãy thử
import re
rx = re.compile('([&#])')
# ^^ fill in the characters here.
strs = rx.sub('\\\\\\1', strs)
Nó có thể không phải là phương pháp hiệu quả nhất nhưng tôi nghĩ nó là dễ nhất.
r'\\\1'
Đến bữa tiệc muộn, nhưng tôi đã mất rất nhiều thời gian với vấn đề này cho đến khi tôi tìm thấy câu trả lời của mình.
Ngắn và ngọt ngào, translate
là vượt trộireplace
. Nếu bạn quan tâm nhiều hơn đến chức năng tối ưu hóa theo thời gian, không sử dụngreplace
.
Đồng thời sử dụng translate
nếu bạn không biết liệu bộ ký tự được thay thế có chồng lấp bộ ký tự được sử dụng để thay thế hay không.
Trường hợp tại điểm:
Sử dụng replace
bạn sẽ ngây thơ mong đợi đoạn trích "1234".replace("1", "2").replace("2", "3").replace("3", "4")
trở lại "2344"
, nhưng thực tế nó sẽ trở lại "4444"
.
Dịch dường như thực hiện những gì OP mong muốn ban đầu.
Bạn có thể xem xét viết một hàm thoát chung:
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
Bằng cách này, bạn có thể làm cho chức năng của mình có thể cấu hình được với một danh sách các ký tự cần được thoát.
FYI, điều này ít hoặc không được sử dụng cho OP nhưng nó có thể được sử dụng cho những người đọc khác (xin đừng downvote, tôi biết điều này).
Là một bài tập hơi vô lý nhưng thú vị, muốn xem liệu tôi có thể sử dụng lập trình chức năng python để thay thế nhiều ký tự không. Tôi khá chắc chắn rằng điều này KHÔNG đánh bại chỉ gọi thay thế () hai lần. Và nếu hiệu suất là một vấn đề, bạn có thể dễ dàng đánh bại điều này trong rỉ sét, C, julia, perl, java, javascript và thậm chí có thể là awk. Nó sử dụng gói 'người trợ giúp' bên ngoài được gọi là pytoolz , được tăng tốc thông qua cython ( cytoolz, đó là gói 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),))))))
Tôi thậm chí sẽ không giải thích điều này bởi vì không ai sẽ sử dụng điều này để thực hiện nhiều thay thế. Tuy nhiên, tôi cảm thấy hơi thành công khi làm điều này và nghĩ rằng nó có thể truyền cảm hứng cho những độc giả khác hoặc giành chiến thắng trong một cuộc thi giấu mã.
Sử dụng giảm có sẵn trong python2.7 và python3. * Bạn có thể dễ dàng thay thế các chuỗi con một cách sạch sẽ và 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"
Trong python2.7, bạn không phải nhập giảm nhưng trong python3. * Bạn phải nhập nó từ mô-đun funcools.
Có thể một vòng lặp đơn giản cho ký tự thay thế:
a = '&#'
to_replace = ['&', '#']
for char in to_replace:
a = a.replace(char, "\\"+char)
print(a)
>>> \&\#
Còn cái này thì sao?
def replace_all(dict, str):
for key in dict:
str = str.replace(key, dict[key])
return str
sau đó
print(replace_all({"&":"\&", "#":"\#"}, "&#"))
đầu ra
\&\#
tương tự như câu trả lời