9 ответов:
замена двух символов
я рассчитал все методы в текущих ответах вместе с одним дополнительным.
С входной строкой
abc&def#ghiи замена & - > \ & и # ->#, самым быстрым было связать вместе замены, такие как:text.replace('&', '\&').replace('#', '\#').тайминги для каждой функции:
- a) 1000000 петель, лучше всего 3: 1.47 МКС на петлю
- b) 1000000 петель, лучше всего 3: 1.51 МКС на петлю
- С) 100000 циклы, лучше всего 3: 12,3 МКС на петлю
- d) 100000 петель, лучше всего 3: 12 МКС на петлю
- e) 100000 петель, лучше всего 3: 3,27 МКС на петлю
- f) 1000000 петель, лучше всего 3: 0.817 МКС на петлю
- g) 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 re def c(text): rx = re.compile('([&#])') text = rx.sub(r'\', text) RX = re.compile('([&#])') def d(text): text = RX.sub(r'\', 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')"
замена 17 символов
вот аналогичный код, чтобы сделать то же самое, но с большим количеством символов, чтобы избежать (\`*_{}>#+-.!$):
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'\', text) RX = re.compile('([\`*_{}[]()>#+-.!$])') def d(text): text = RX.sub(r'\', 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:
- a) 100000 петель, лучше всего 3: 6.72 МКС на петлю
- b) 100000 петель, лучше всего 3: 2.64 МКС на петлю
- c) 100000 петель, лучше всего 3: 11,9 МКС на петлю
- d) 100000 петель, лучше всего 3: 4,92 МКС на петлю
- e) 100000 петель, лучше всего 3: 2.96 МКС на петлю
- f) 100000 петель, лучше всего 3: 4,29 МКС на петлю
- g) 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$):
- a) 100000 петель, лучше всего 3: 7.59 МКС на петлю
- b) 100000 петель, лучше всего 3: 6.54 МКС на петлю
- c) 100000 петель, лучше всего 3: 16,9 МКС на петлю
- d) 100000 петель, лучше всего 3: 7,29 МКС на петлю
- e) 100000 петель, лучше всего 3: 12,2 МКС на петлю
- f) 100000 петель, лучше всего 3: 5.38 МКС на петлю
- g) 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)С более коротким входом:
- ab) 100000 петель, лучше всего 3: 7,05 МКС на петлю
- ba) 100000 петель, лучше всего 3: 2,4 МКС на петлю
С более вход:
- ab) 100000 петель, лучше всего 3: 7,71 МКС на петлю
- ba) 100000 петель, лучше всего 3: 6.08 МКС на петлю
так что я собираюсь использовать
baдля удобочитаемости и скорости.дополнительное соглашение
подсказано haccks в комментариях, одна разница между
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!
>>> string="abc&def#ghi" >>> for ch in ['&','#']: ... if ch in string: ... string=string.replace(ch,"\"+ch) ... >>> print string abc\&def\#ghi
просто сеть
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
вы всегда будете добавлять обратную косую черту? Если да, то попробуйте
import re rx = re.compile('([&#])') # ^^ fill in the characters here. strs = rx.sub('\\\1', strs)может быть, это не самый эффективный метод, но я думаю, что это самый простой.
вот метод python3 с использованием
str.translateиstr.maketrans:s = "abc&def#ghi" print(s.translate(str.maketrans({'&': '\&', '#': '\#'})))печатная строка
abc\&def\#ghi.
вы можете рассмотреть возможность написания общей функции escape:
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, это мало или нет пользы для OP, но это может быть полезно для других читателей (пожалуйста, не понижайте голос, я знаю об этом).
как несколько смешное, но интересное упражнение, хотел посмотреть, могу ли я использовать функциональное программирование python для замены нескольких символов. Я уверен, что это не бьет просто вызов replace() дважды. И если бы производительность была проблемой, вы могли бы легко победить это в rust, C, julia, 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),))))))Я даже не собираюсь объяснять это, потому что никто не потрудился бы использовать это для выполнения нескольких замен. Тем не менее, я чувствовал себя несколько опытным в этом и думал, что это может вдохновить других читателей или выиграть конкурс обфускации кода.
>>> a = '&#' >>> print a.replace('&', r'\&') \&# >>> print a.replace('#', r'\#') &\# >>>вы хотите использовать "сырую" строку (обозначенную префиксом " r " заменяющей строки), так как необработанные строки не обрабатывают обратную косую черту специально.
используя reduce, который доступен в python2. 7 и python3.* вы можете легко заменить нескольких подстрок в чистые и подходящие для Python путь.
# 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 вам не нужно импортировать reduce, но в python3.* вы должны импортировать его из модуль functools.
Comments