Хотя str.replace
может заменить только одну подстроку другой, re.sub
может заменить шаблон.
In [55]: eSToAvoid = 'éêèÉÊÈ'
In [58]: import re
контрольные примеры:
In [61]: re.sub(r'[éêèÉÊÈ]', 'e', 'foobar')
Out[61]: 'foobar'
In [62]: re.sub(r'[éêèÉÊÈ]', 'e', eSToAvoid)
Out[62]: 'eeeeee'
In [63]: re.sub(r'[éêèÉÊÈ]', 'e', 'testingè,É foobar è É')
Out[63]: 'testinge,e foobar e e'
Подход с заменой строки :
In [70]: astr = 'testingè,É foobar è É'
...: for e in eSToAvoid:
...: astr = astr.replace(e,'e')
...:
In [71]: astr
Out[71]: 'testinge,e foobar e e'
замена применяется последовательно к astr
. Это не может быть выражено как понимание списка (или map
). Понимание списка наиболее естественно заменяет al oop, который собирает свои результаты в списке (с list.append
).
Нет ничего плохого в для l oop. Это на самом деле быстрее:
In [72]: %%timeit
...: astr = 'testingè,É foobar è É'
...: for e in eSToAvoid:
...: astr = astr.replace(e,'e')
...:
...:
1.37 µs ± 8.96 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [73]: timeit re.sub(r'[éêèÉÊÈ]', 'e', 'testingè,É foobar è É')
2.79 µs ± 15.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [77]: timeit astr.translate(str.maketrans(eSToAvoid, 'e' * len(eSToAvoid)))
2.56 µs ± 14.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
уменьшение
In [93]: from functools import reduce
In [96]: reduce(lambda s,e: s.replace(e,'e'),eSToAvoid, 'testingè,É foobar è É' )
Out[96]: 'testinge,e foobar e e'
In [97]: timeit reduce(lambda s,e: s.replace(e,'e'),eSToAvoid, 'testingè,É foobar è É' )
2.11 µs ± 32.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Для развлечения вы также можете изучить некоторые из представленных здесь идей:
Самый чистый способ комбинировать сокращение и отобразите в Python
Вы хотите «накапливать» изменения, и для этого вам нужен какой-то аккумулятор, что-то, что держится до последней замены. itertools
имеет функцию accumulate
, а в Py 3.8 введен * оператор моржа :=
.
генератор
In [110]: def foo(astr, es):
...: for e in es:
...: astr = astr.replace(e,'e')
...: yield astr
...:
In [111]: list(foo(astr, eSToAvoid))
Out[111]:
['testingè,É foobar è É',
'testingè,É foobar è É',
'testinge,É foobar e É',
'testinge,e foobar e e',
'testinge,e foobar e e',
'testinge,e foobar e e']
или [s for s in foo(astr, eSToAvoid)]
вместо list()
. Это подчеркивает тот факт, что понимание списка возвращает список строк, даже если строки накапливают изменения.