Самая быстрая реализация для выполнения нескольких подстановок строк в Python

Есть ли какой-либо рекомендуемый способ выполнения нескольких строковых подстановок, кроме как «заменить» цепочку на строку (т. Е. Text.replace (a, b) .replace (c, d) .replace (e, f) …)? Как бы вы, например, реализовали быструю функцию, которая ведет себя как PHP htmlspecialchars в Python?

Я сравнивал (1) множественный метод «replace», (2) метод регулярных выражений и (3) метод Мэтта Андерсона.

При n = 10 пробегах результаты выглядели следующим образом:

На 100 символов:

 TIME: 0 мс [replace_method (str)]
 TIME: 5 ms [regular_expression_method (str, dict)]
 TIME: 1 мс [matts_multi_replace_method (list, str)]

На 1000 символов:

 TIME: 0 мс [replace_method (str)]
 TIME: 3 мс [regular_expression_method (str, dict)]
 TIME: 2 ms [matts_multi_replace_method (list, str)]

На 10000 символов:

 TIME: 3 мс [replace_method (str)]
 TIME: 7 ms [regular_expression_method (str, dict)]
 TIME: 5 ms [matts_multi_replace_method (list, str)]

На 100000 символов:

 ВРЕМЯ: 36 мс [replace_method (str)]
 TIME: 46 ms [regular_expression_method (str, dict)]
 TIME: 39 ms [matts_multi_replace_method (list, str)]

На 1000000 символов:

 TIME: 318 мс [replace_method (str)]
 ВРЕМЯ: 360 мс [regular_expression_method (str, dict)]
 TIME: 320 мс [matts_multi_replace_method (list, str)]

По 3687809 символов:

 ВРЕМЯ: 1.277524 сек [replace_method (str)]
 TIME: 1.290590 сек [regular_expression_method (str, dict)]
 TIME: 1.116601 sec [matts_multi_replace_method (list, str)]

Так что пригодился Мэтту за избиение метода «replace» на довольно большой входной строке.

Кто-нибудь получил идеи для избиения его на более мелкой струне?

Может быть, что-то вроде следующего? Разделите текст на части с помощью первого элемента «from», который нужно заменить, а затем рекурсивно разделить каждую из этих частей на части со следующим «из» предмета, который нужно заменить, и так далее, пока вы не посетили все ваши замены , Затем присоединитесь к элементу замены «to» для каждого, когда завершена рекурсивная функция.

Немного трудно обернуть голову вокруг следующего кода, возможно (это было для меня, и я написал его), но, похоже, он работает по назначению. Я не сравнивал это, но я подозреваю, что это будет достаточно быстро.

def multi_replace(pairs, text): stack = list(pairs) stack.reverse() def replace(stack, parts): if not stack: return parts # copy the stack so I don't disturb parallel recursions stack = list(stack) from_, to = stack.pop() #print 'split (%r=>%r)' % (from_, to), parts split_parts = [replace(stack, part.split(from_)) for part in parts] parts = [to.join(split_subparts) for split_subparts in split_parts] #print 'join (%r=>%r)' % (from_, to), parts return parts return replace(stack, [text])[0] print multi_replace( [('foo', 'bar'), ('baaz', 'foo'), ('quux', 'moop')], 'foobarbaazfooquuxquux') 

для:

 barbarfoobarmoopmoop 

Как быстро? Кроме того, насколько велики ваши строки?

Существует довольно простой рецепт создания регулярного выражения для выполнения задания на другом сайте. Для обработки метасимволов регулярных выражений может потребоваться некоторая настройка. Я не слишком внимательно смотрел.

Если это не достаточно хорошо, вам, вероятно, нужно написать код C, честно говоря. Вы можете создать простой конечный автомат для выполнения всех замен, а затем обработать любой байт строки байтом без возврата по машине, чтобы фактически выполнить работу. Однако я сомневаюсь, что вы побьете двигатель регулярного выражения, не перейдя на C и не оптимизируя это.

Обычно метод .replace превосходит все другие методы. (См. Мои тесты выше.)