weranda
@weranda

Почему строковый метод .replace() в python не проводит нужное количество замен?

Приветствую

Не понимаю почему строковый метод замены не проводит нужное количество замен в строке.

Пример:
a = '0 1  2   3    4     5      6       7        8         9'
print(a.replace('  ', ' ', 2000))
>>> 0 1  2 3  4   5  6   7    8   9


Казалось бы, должны остаться только одинарные пробелы, но нет – они остаются даже в том случае, если использовать две тысячи замен.

Поясните пожалуйста почему происходит именно так.

P.S.
Понятно что можно использовать регулярные выражения, но интересует работа именно этого метода.
  • Вопрос задан
  • 852 просмотра
Решения вопроса 3
fox_12
@fox_12 Куратор тега Python
Расставляю биты, управляю заряженными частицами
Посчитаем количество пробелов в промежутках между строками в вашем примере:
>>> a = '0 1  2   3    4     5      6       7        8         9'
>>> import re
>>> [len(x) for x in re.split('\d',a)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0]

вы меняете каждые 3 пробела на 1
c=a.replace('   ', ' ', 2000)
>>> [len(x) for x in re.split('\d',c)]
[0, 1, 2, 1, 2, 3, 2, 3, 4, 3, 0]

Соответственно там где количество пробелов менее 3 - их оставляем
Там где более или равно - каждые три пробела меняем на один + остаток не делящийся на 3
К примеру для 8 пробелов:
>>> (lambda x: x//3 + x%3)(8)
4

Для 9:
>>> (lambda x: x//3 + x%3)(9)
3

Параметр 2000 указывает лишь на то, что в каждом случае провести не более 2000 замен. Поскольку у вас количество пробелов в примере заведомо меньшее - этот параметр не оказывает никакого влияния. Если было бы больше - то было бы произведено количество замен, не большее 2000.
Наглядно изменение третьего параметра:
>>> [len(x) for x in re.split('\d',a.replace('   ', ' ', 0))]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
>>> [len(x) for x in re.split('\d',a.replace('   ', ' ', 1))]
[0, 1, 2, 1, 4, 5, 6, 7, 8, 9, 0]
>>> [len(x) for x in re.split('\d',a.replace('   ', ' ', 2))]
[0, 1, 2, 1, 2, 5, 6, 7, 8, 9, 0]
>>> [len(x) for x in re.split('\d',a.replace('   ', ' ', 3))]
[0, 1, 2, 1, 2, 3, 6, 7, 8, 9, 0]
>>> [len(x) for x in re.split('\d',a.replace('   ', ' ', 4))]
[0, 1, 2, 1, 2, 3, 4, 7, 8, 9, 0]
>>> [len(x) for x in re.split('\d',a.replace('   ', ' ', 5))]
[0, 1, 2, 1, 2, 3, 2, 7, 8, 9, 0]
...
Ответ написан
Оно сделало то, что попросили ее сделать, делайте несколько проходов.
Ответ написан
weranda
@weranda Автор вопроса
Владимир
Александр Опарин
Правильно ли я понял?

Замены с помощью этого метода последовательны и начинаются с левой части строки. Метод последовательно обрабатывает в данном примере первые два пробела – меняет их на один и более не возвращается к замененным элементам и идет дальше, т.е. продолжает уже поиск совпадений начиная с третьего элемента. На следуещем совпадении метод делает тоже самое и также не возвращается к предыдущим элементам, несмотря на то, что там два пробела, а ничинает поиск совпадений уже с пятого элемента. Не найдя более совпадений, метод останавливается даже в том случае, когда указано большое количество замен. Он просто линейно слева направо делает замены и не возвращается обратно, как это происходит с регулярными выражениями.

0862d403e57f4c40b843b7c6ec82fefb.png
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы