Форум сайта python.su
Здравствуйте.
Есть такая строка:
{9}:{10}:текст:{6}:{7}:{4}text::{5}::::{11}@{12}:{13}
Все числа в ней размещены между фигурных скобок
Задача: написать функцию, которая будет уменьшать все числа в строке на 1.
Чтобы на выходе получить:
{8}:{9}:текст:{5}:{6}:{3}text:{4}::::{10}@{11}:{12}
С учетом того, что в строке есть как минимум одно число в фигурных скобках.
Если есть числа НЕ в фигурных скобках, то их трогать не надо.
В фигурных скобках могут быть только числа.
Отредактировано for_soul (Янв. 29, 2017 16:52:34)
Офлайн
Не смог просто ждать. Набросал функцию. Оцените, пожалуйста.
Работает вроде правильно, с данной строкой.
out_stroka = '{9}:{10}:http:{6}:{7}:{4}:{5}::::{11}@{12}:{13}' def minus_1(stroka): list_out = [] list_in = re.split('}|{', stroka) for _ in list_in: if _.isdigit(): list_out.append('{' + str(int(_) - 1) + '}') else: list_out.append(_) return ''.join(list_out) print(minus_1(out_stroka))
Офлайн
>>> import re >>> >>> s = '{9}:{10}:текст:{6}:{7}:{4}text::{5}::::{11}@{12}:{13}' >>> >>> def tr(s): ... return '{}{}{}'.format(s[0], int(s[1:-1]) - 1, s[-1]) ... >>> out = re.sub(r'\{\d+\}', lambda mo: tr(mo.group()), s) >>> out '{8}:{9}:текст:{5}:{6}:{3}text::{4}::::{10}@{11}:{12}' >>>
>>> import re >>> >>> s = '{9}:{10}:текст:{6}:{7}:{4}text::{5}::::{11}@{12}:{13}' >>> >>> def tr(s): ... num = s[1:-1] ... if num[0] == '0' and len(num) > 1: ... out = s ... else: ... out = '{}{}{}'.format(s[0], int(num) - 1, s[-1]) ... return out ... >>> out = re.sub(r'\{\d+\}', lambda mo: tr(mo.group()), s) >>> out '{8}:{9}:текст:{5}:{6}:{3}text::{4}::::{10}@{11}:{12}' >>>
for_soulНу, он даст ошибку на строке “}10{”, это если сходу его ломать (там ещё много строк можно придумать), не смотря на чисто питоновские ошибки вроде использования подчёркивания там, где не принято это делать.
Оцените, пожалуйста.
>>> def minus_1(stroka): ... list_out = [] ... list_in = re.split('}|{', stroka) ... for _ in list_in: ... if _.isdigit(): ... list_out.append('{' + str(int(_) - 1) + '}') ... else: ... list_out.append(_) ... return ''.join(list_out) ... >>> minus_1('}10{') '{9}' >>>
Отредактировано py.user.next (Янв. 30, 2017 10:09:30)
Офлайн
py.user.nextСпасибо. Работает.
lambda mo: tr(mo.group())
Отредактировано for_soul (Янв. 29, 2017 21:04:12)
Офлайн
можно проще:
# s = '{9}:{10}:http:{6}:{7}:{4}:{5}::10.05:текст:{11}@{12}:{13}' tmp = '' out = '' for i in s: tmp += i if i == '{' : out += tmp tmp = '' elif i == '}': try : out += str(int(tmp[:-1]) - 1 ) + '}' except: out += tmp tmp = '' out += tmp print s print out
Отредактировано vic57 (Янв. 29, 2017 23:22:31)
Офлайн
vic57
можно проще:
>>> def f(s): ... tmp = '' ... out = '' ... for i in s: ... tmp += i ... if i == '{' : ... out += tmp ... tmp = '' ... elif i == '}': ... try : out += str(int(tmp[:-1]) - 1 ) + '}' ... except: out += tmp ... tmp = '' ... out += tmp ... return out ... >>> s = '{9}:{10}:http:{6}:{7}:{4}:{5}::10.05:текст:{11}@{12}:{13}' >>> >>> print s {9}:{10}:http:{6}:{7}:{4}:{5}::10.05:текст:{11}@{12}:{13} >>> print f(s) {8}:{9}:http:{5}:{6}:{3}:{4}::10.05:текст:{10}@{11}:{12} >>> >>> print f('{abc') { >>>
for_soulre.sub() когда находит совпадение, это совпадение представляет из себя объект, в котором хранится вся информация о совпадении (где оно в строке находится, какая подстрока совпала, какие там группы есть). Вот этот объект потом пытается замениться. Если ему предлагают замениться на строку, то он просто отбрасывается и вместо него вставляется строка. А если ему предлагают замениться по функции, то эта функция считается такого вида “принимает объект совпадения и возвращает какую-то строку”, потом исходный объект совпадения отбрасывается и вместо него вставляется эта возвращённая из функции строка.
На просторах интернета так и не нашел внятного пояснения метода group()
Не могли бы вкратце объяснить?
lambda mo: tr(mo.group())
>>> import re >>> >>> mo = re.search(r'(a)(b)(c)', 'abcdef') >>> mo.group(0) 'abc' >>> mo.group() 'abc' >>> mo.group(1) 'a' >>> mo.group(2) 'b' >>> mo.group(3) 'c' >>> mo.group(1, 2, 3) ('a', 'b', 'c') >>> mo.group(1, 2, 3, 1, 2, 3) ('a', 'b', 'c', 'a', 'b', 'c') >>> >>> mo.groups() ('a', 'b', 'c') >>> >>> mo <_sre.SRE_Match object at 0xb73e5660> >>>
Отредактировано py.user.next (Янв. 30, 2017 03:43:34)
Офлайн
py.user.next
строку пропустили после цикла, ничего не портит
s = '{9}:{21}:http:{6}:{7}:{4}:{5}::10.05:текст:{11}@{12}:{13}:qqq{AS}DFФЫА{{{' def f(s): tmp = '' out = '' for i in s: tmp += i if i == '{' : out += tmp tmp = '' elif i == '}': try : out += str(int(tmp[:-1]) - 1 ) + '}' except: out += tmp tmp = '' out += tmp #остаток строки return out print 's:',s print 'out:',f(s)
Отредактировано vic57 (Янв. 30, 2017 08:29:44)
Офлайн
vic57Не, это ты поправил просто. Ну, я тогда серьёзно взялся проверить твой код :)
строку пропустили после цикла, ничего не портит
def f(s): tmp = '' out = '' for i in s: tmp += i if i == '{' : out += tmp tmp = '' elif i == '}': try : out += str(int(tmp[:-1]) - 1 ) + '}' except: out += tmp tmp = '' out += tmp #остаток строки return out
[guest@localhost bracenum]$ python -mdoctest bracenum1.doct
**********************************************************************
File "bracenum1.doct", line 30, in bracenum1.doct
Failed example:
f('{1 }')
Expected:
'{1 }'
Got:
'{0}'
**********************************************************************
File "bracenum1.doct", line 32, in bracenum1.doct
Failed example:
f('{ 1}')
Expected:
'{ 1}'
Got:
'{0}'
**********************************************************************
File "bracenum1.doct", line 34, in bracenum1.doct
Failed example:
f('{\n1}')
Expected:
'{\n1}'
Got:
'{0}'
**********************************************************************
File "bracenum1.doct", line 36, in bracenum1.doct
Failed example:
f('{1\n}')
Expected:
'{1\n}'
Got:
'{0}'
**********************************************************************
File "bracenum1.doct", line 41, in bracenum1.doct
Failed example:
f('{00}')
Expected:
'{00}'
Got:
'{-1}'
**********************************************************************
File "bracenum1.doct", line 43, in bracenum1.doct
Failed example:
f('{01}')
Expected:
'{01}'
Got:
'{0}'
**********************************************************************
1 items had failures:
6 of 20 in bracenum1.doct
***Test Failed*** 6 failures.
[guest@localhost bracenum]$
Отредактировано py.user.next (Янв. 30, 2017 10:14:37)
Офлайн
py.user.next
1.поправил я еще вчера,что видно по времени правки. ты был в офлайне
2.по условию ТС в скобках только цифры, без всяких пробелов
Офлайн
vic57Ладно, наверное, я ошибся и что-то там передвинул.
1.поправил я еще вчера,что видно по времени правки.
vic57Ну, мы можем достроить просто задачу до общей (где всё-таки нет этого ограничения), чтобы соблюсти правило слабого предусловия (слабое предусловие делает функцию применимой для решения большего числа задач). Просто тестирование через исключение при приведению к int нехорошая практика, так как зависит от семантики функции, у которой вообще своё понимание чисел, например int(“aa”, 16) и прочее. И эти пробелы, которые она может принимать, - как раз доказательство этому (не предназначена она для таких точных проверок, только для преобразований). Даже isdigit() здесь даст более точную картину. Ну, и числа вида 002 твоя версия превращает в 1, а куда ведущие нули тогда деваются? Хотя я за то, чтобы вообще такие числа не трогать, а считать их нечисловой лексемой, как и {+1} и подобные.
2.по условию ТС в скобках только цифры, без всяких пробелов
Отредактировано py.user.next (Янв. 30, 2017 12:34:08)
Офлайн