Мені потрібно замінити деякі символи так: &
➔ \&
, #
➔ \#
, ...
Я кодував так, але, мабуть, має бути якийсь кращий спосіб. Якісь підказки?
strs = strs.replace('&', '\&')
strs = strs.replace('#', '\#')
...
Мені потрібно замінити деякі символи так: &
➔ \&
, #
➔ \#
, ...
Я кодував так, але, мабуть, має бути якийсь кращий спосіб. Якісь підказки?
strs = strs.replace('&', '\&')
strs = strs.replace('#', '\#')
...
Відповіді:
Я приурочив усі методи в поточних відповідях разом з одним додатковим.
З вхідного рядка abc&def#ghi
і замінюючи & -> \ & і # -> \ #, найшвидший спосіб був прикувати разом ці заміни , як це: text.replace('&', '\&').replace('#', '\#')
.
Час виконання кожної функції:
Ось функції:
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'\#')
Призначається так:
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')"
Ось подібний код зробити те ж саме, але для втечі більше символів (\ `* _ {}> # + -. $):
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'\$')
Ось результати для тієї ж вхідної рядок abc&def#ghi
:
І з більш довгим рядком введення ( ## *Something* and [another] thing in a longer sentence with {more} things to replace$
):
Додавання декількох варіантів:
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)
З коротшим введенням:
При більш тривалому введенні:
Тому я збираюся використовувати ba
для читабельності та швидкості.
Запропоновані хаками в коментарях, одна різниця між ab
і ba
- це if 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 та на іншій машині, ніж попередній набір, тому неможливо порівняти безпосередньо.
╭────────────╥──────┬───────────────┬──────┬──────────────────╮
│ 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 - це в 3 рази швидше, ніж Python 2 ! Немає великої різниці між найповільнішими на Python 3 та найшвидшими на Python 2!
if c in text:
потрібно в ba
?
1.45 usec per loop
і без: 5.3 usec per loop
, довжини рядка, з: 4.38 usec per loop
і без: 7.03 usec per loop
. (Зауважте, що вони безпосередньо не порівнянні з результатами вище, тому що це інша машина тощо).
replace
викликається лише тоді, коли c
вона виявляється text
у випадку, ba
поки вона викликається в кожній ітерації в 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)
? Не string.replace(ch,"\\"+ch)
достатньо просто ?
Просто ланцюг 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
Ось метод python3 з використанням str.translate
та str.maketrans
:
s = "abc&def#ghi"
print(s.translate(str.maketrans({'&': '\&', '#': '\#'})))
Друкований рядок є abc\&def\#ghi
.
.translate()
повільніше, ніж три ланцюгові .replace()
(використовуючи CPython 3.6.4).
replace()
себе, але додав цю відповідь заради повноти.
'\#'
діє? не повинно бути r'\#'
чи '\\#'
? Можливо, може виникнути проблема із форматуванням блоку коду.
Пізно на вечірку, але я втратив багато часу з цим питанням, поки не знайшов своєї відповіді.
Короткий і милий, translate
перевершуєreplace
. Якщо вас більше цікавить функціональність з часом оптимізації, не використовуйте replace
.
Також використовуйте, translate
якщо ви не знаєте, чи набір символів, які потрібно замінити, перекриває набір символів, які використовуються для заміни.
Справа в точці:
Використовуючи, replace
ви наївно очікуєте, що фрагмент "1234".replace("1", "2").replace("2", "3").replace("3", "4")
повернеться "2344"
, але він повернеться фактично "4444"
.
Переклад, здається, виконує те, що OP спочатку бажав.
Ви можете розглянути можливість створення загальної функції втечі:
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
Таким чином ви можете зробити свою функцію настроюваною зі списком символів, який слід уникати.
FYI, це дуже мало користі для ОП, але це може бути корисно іншим читачам (будь ласка, не зволікайте, я це знаю).
Як дещо смішна, але цікава вправа, хотілося побачити, чи можу я використати функціональне програмування python для заміни декількох символів. Я впевнений, що це НЕ перемагає просто виклик заміну () двічі. І якщо продуктивність була проблемою, ви можете легко перемогти це в іржі, С, Джулія, Перл, Ява, javascript і, можливо, навіть awk. Він використовує зовнішній пакет "помічників" під назвою pytoolz , прискорений за допомогою цитону ( 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),))))))
Я навіть не збираюся пояснювати це тим, що ніхто не заважає використовувати це для багаторазової заміни. Тим не менше, я відчував себе дещо досягнутим у цьому і думав, що це може надихнути інших читачів або виграти конкурс з придушення коду.
Використовуючи зменшення, яке доступне в python2.7 та python3. *, Ви можете легко замінити нескінченні підряди чистим та пітонічним способом.
# 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 вам не потрібно імпортувати скорочення, а у python3. * Ви повинні імпортувати його з модуля functools.
Можливо, простий цикл для символів замінити:
a = '&#'
to_replace = ['&', '#']
for char in to_replace:
a = a.replace(char, "\\"+char)
print(a)
>>> \&\#