Я рассчитал все методы в текущих ответах вместе с одним дополнительным.
С входной строки abc&def#ghiи заменяя & -> \ & и # -> \ #, самый быстрый способ был приковать вместе эти замены , как это: text.replace('&', '\&').replace('#', '\#').
Сроки для каждой функции:
а) 1000000 петель, лучшее из 3: 1,47 мкс на петлю
б) 1000000 петель, лучшее из 3: 1,51 мкс на петлю
в) 100000 петель, лучшее из 3: 12,3 мкс на петлю
г) 100000 петель, лучшее из 3: 12 мкс на петлю
д) 100000 петель, лучшее из 3: 3,27 мкс на петлю
f) 1000000 петель, лучшее из 3: 0,817 мкс на петлю
г) 100000 петель, лучшее из 3: 3,64 мкс на петлю
h) 1000000 петель, лучшее из 3: 0,927 мкс на петлю
i) 1000000 петель, лучшее из 3: 0,814 мкс на петлю
Вот функции:
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 redef 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'\#')
Вот аналогичный код, чтобы сделать то же самое, но с большим количеством символов для выхода (\ `* _ {}> # + -.! $):
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 redef 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'\$')
Вот результаты для той же входной строки abc&def#ghi:
а) 100000 петель, лучшее из 3: 6,72 мкс на петлю
б) 100000 петель, лучшее из 3: 2,64 мкс на петлю
в) 100000 петель, лучшее из 3: 11,9 мкс на петлю
г) 100000 петель, лучшее из 3: 4,92 мкс на петлю
д) 100000 петель, лучшее из 3: 2,96 мкс на петлю
f) 100000 петель, лучшее из 3: 4,29 мкс на петлю
г) 100000 петель, лучшее из 3: 4,68 мкс на петлю
h) 100000 петель, лучшее из 3: 4,73 мкс на петлю
i) 100000 циклов, лучшее из 3: 4,24 мкс на цикл
И с более длинной входной строкой ( ## *Something* and [another] thing in a longer sentence with {more} things to replace$):
а) 100000 петель, лучшее из 3: 7,59 мкс на петлю
б) 100000 петель, лучшее из 3: 6,54 мкс на петлю
в) 100000 петель, лучшее из 3: 16,9 мкс на петлю
d) 100000 петель, лучшее из 3: 7,29 мкс на петлю
e) 100000 петель, лучшее из 3: 12,2 мкс на петлю
f) 100000 петель, лучшее из 3: 5,38 мкс на петлю
г) 10000 петель, лучшее из 3: 21,7 мкс на петлю
h) 100000 петель, лучшее из 3: 5,7 мкс на петлю
i) 100000 циклов, лучшее из 3: 5,13 мкс на цикл
Добавляем пару вариантов:
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)
С более коротким вводом:
а.б) 100000 петель, лучшее из 3: 7,05 мкс на петлю
ba) 100000 петель, лучшее из 3: 2,4 мкс на петлю
С более длинным вводом:
а.б) 100000 циклов, лучшее из 3: 7,71 мкс на цикл
ba) 100000 петель, лучшее из 3: 6,08 мкс на петлю
Так что я собираюсь использовать 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!
@haccks Это не обязательно, но это в 2-3 раза быстрее. Короткая строка, с: 1.45 usec per loopи без: 5.3 usec per loop, длинной строки, с: 4.38 usec per loopи без: 7.03 usec per loop. (Обратите внимание, что они не сравнимы напрямую с результатами, приведенными выше, потому что это другая машина и т. Д.)
Hugo
1
@Hugo; Я думаю, что эта разница во времени вызвана тем, что replaceвызывается только тогда, когда cнаходится textв случае, baкогда она вызывается в каждой итерации в ab.
хак
2
@haccks Спасибо, я обновил свой ответ дополнительными временами: добавление проверки лучше для обоих, но самый большой урок - Python 3 - до 3 раз быстрее!
Хьюго
73
>>> string="abc&def#ghi">>>for ch in['&','#']:...if ch in string:... string=string.replace(ch,"\\"+ch)...>>>print string
abc\&def\#ghi
Зачем нужен двойной обратный слеш? Почему просто "\" не работает?
Аксолотль
3
Двойная обратная косая черта экранирует обратную косую черту, в противном случае python интерпретирует символ "\" как буквальный символ кавычки в еще открытой строке.
Riet
Зачем тебе это string=string.replace(ch,"\\"+ch)? Разве не string.replace(ch,"\\"+ch)достаточно?
MattSom
1
@MattSom replace () не изменяет исходную строку, но возвращает копию. Таким образом, вам нужно присвоение кода, чтобы иметь какой-либо эффект.
Бен Брайан
3
Вам действительно нужно, если? Это похоже на дублирование того, что замена будет делать в любом случае.
Опоздал на вечеринку, но я потерял много времени на эту проблему, пока не нашел свой ответ.
Короткий и сладкий, translateпревосходящийreplace . Если вас больше интересует функциональность с течением времени, не используйте оптимизацию replace.
Также используйте, translateесли вы не знаете, перекрывает ли набор заменяемых символов набор символов, используемых для замены.
Дело в точке:
При использовании replaceвы наивно ожидаете, что фрагмент "1234".replace("1", "2").replace("2", "3").replace("3", "4")вернется "2344", но на самом деле он вернется "4444".
Похоже, что перевод выполняет то, что изначально хотел OP.
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
Таким образом, вы можете сделать вашу функцию настраиваемой со списком символов, которые должны быть экранированы.
К вашему сведению, это мало что значит для ОП, но может быть полезно другим читателям (пожалуйста, не понижайте голос, я знаю об этом).
Как смешное, но интересное упражнение, я хотел посмотреть, смогу ли я использовать функциональное программирование на Python для замены нескольких символов. Я почти уверен, что это НЕ бьет просто вызов replace () дважды. И если производительность была проблемой, вы могли бы легко победить это в ржавчине, C, Джулия, Perl, Java, Javascript и, возможно, даже awk. Он использует внешний пакет помощников, называемый pytoolz , ускоренный через cython ( 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),))))))
Я даже не собираюсь объяснять это, потому что никто не потрудится использовать это для выполнения множественной замены. Тем не менее, я почувствовал, что достиг этого, и подумал, что это может вдохновить других читателей или выиграть конкурс обфускации кода.
Используя Reduction, который доступен в python2.7 и python3. *, Вы можете легко заменить множественные подстроки чистым и 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"
В python2.7 вам не нужно импортировать Reduce, но в Python3. * Вы должны импортировать его из модуля functools.
>>> a ='&#'>>>print a.replace('&', r'\&')
\&#>>>print a.replace('#', r'\#')&\#
>>>
Вы хотите использовать «сырую» строку (обозначенную префиксом «r» строки замены), поскольку необработанные строки не обрабатывают обратную косую черту специально.
Ответы:
Замена двух символов
Я рассчитал все методы в текущих ответах вместе с одним дополнительным.
С входной строки
abc&def#ghi
и заменяя & -> \ & и # -> \ #, самый быстрый способ был приковать вместе эти замены , как это:text.replace('&', '\&').replace('#', '\#')
.Сроки для каждой функции:
Вот функции:
Приурочен так:
Замена 17 символов
Вот аналогичный код, чтобы сделать то же самое, но с большим количеством символов для выхода (\ `* _ {}> # + -.! $):
Вот результаты для той же входной строки
abc&def#ghi
:И с более длинной входной строкой (
## *Something* and [another] thing in a longer sentence with {more} things to replace$
):Добавляем пару вариантов:
С более коротким вводом:
С более длинным вводом:
Так что я собираюсь использовать
ba
для удобства чтения и скорости.добавление
По подсказкам хаков в комментариях, одним отличием
ab
иba
являетсяif c in text:
проверка. Давайте проверим их еще на двух вариантах:Время в мкс на цикл в Python 2.7.14 и 3.6.3 и на компьютере, отличном от предыдущего, поэтому нельзя сравнивать напрямую.
Мы можем сделать вывод, что:
Те, у кого есть чек, в 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=string.replace(ch,"\\"+ch)
? Разве неstring.replace(ch,"\\"+ch)
достаточно?Просто цепочка
replace
функций, как этоЕсли замен будет больше, вы можете сделать это в общем виде
источник
Вот метод python3, использующий
str.translate
иstr.maketrans
:Печататься строка
abc\&def\#ghi
.источник
.translate()
происходит медленнее, чем три.replace()
(с использованием CPython 3.6.4).replace()
себя, но я добавил этот ответ для полноты картины.'\#'
действует? не должно бытьr'\#'
или'\\#'
? Может быть проблема форматирования блока кода, возможно.Вы всегда собираетесь добавить обратную косую черту? Если так, попробуйте
Возможно, это не самый эффективный метод, но я думаю, что он самый простой.
источник
r'\\\1'
Опоздал на вечеринку, но я потерял много времени на эту проблему, пока не нашел свой ответ.
Короткий и сладкий,
translate
превосходящийreplace
. Если вас больше интересует функциональность с течением времени, не используйте оптимизациюreplace
.Также используйте,
translate
если вы не знаете, перекрывает ли набор заменяемых символов набор символов, используемых для замены.Дело в точке:
При использовании
replace
вы наивно ожидаете, что фрагмент"1234".replace("1", "2").replace("2", "3").replace("3", "4")
вернется"2344"
, но на самом деле он вернется"4444"
.Похоже, что перевод выполняет то, что изначально хотел OP.
источник
Вы можете написать общую функцию escape:
Таким образом, вы можете сделать вашу функцию настраиваемой со списком символов, которые должны быть экранированы.
источник
К вашему сведению, это мало что значит для ОП, но может быть полезно другим читателям (пожалуйста, не понижайте голос, я знаю об этом).
Как смешное, но интересное упражнение, я хотел посмотреть, смогу ли я использовать функциональное программирование на Python для замены нескольких символов. Я почти уверен, что это НЕ бьет просто вызов replace () дважды. И если производительность была проблемой, вы могли бы легко победить это в ржавчине, C, Джулия, Perl, Java, Javascript и, возможно, даже awk. Он использует внешний пакет помощников, называемый pytoolz , ускоренный через cython ( cytoolz, это пакет pypi ).
Я даже не собираюсь объяснять это, потому что никто не потрудится использовать это для выполнения множественной замены. Тем не менее, я почувствовал, что достиг этого, и подумал, что это может вдохновить других читателей или выиграть конкурс обфускации кода.
источник
Используя Reduction, который доступен в python2.7 и python3. *, Вы можете легко заменить множественные подстроки чистым и pythonic способом.
В python2.7 вам не нужно импортировать Reduce, но в Python3. * Вы должны импортировать его из модуля functools.
источник
Может быть, простой цикл для замены символов:
источник
Как насчет этого?
затем
вывод
похоже на ответ
источник
Вы хотите использовать «сырую» строку (обозначенную префиксом «r» строки замены), поскольку необработанные строки не обрабатывают обратную косую черту специально.
источник
продвинутый способ с помощью регулярных выражений
источник