Обратные помеченные подстроки в строке

У меня есть строка, в которой каждая отмеченная подстрока в < а также >должен быть перевернут (скобки не гнездятся). Например,

"hello <wolfrevokcats>, how <t uoy era>oday?"

должен стать

 "hello stackru, how are you today?"

Моя текущая идея состоит в том, чтобы перебрать строку и найти пары индексов, где < а также > являются. Затем просто нарежьте строку и снова соедините кусочки со всем, что было между маркерами в обратном порядке. Это правильный подход? Есть ли очевидное / лучшее решение?

4 ответа

Решение

Это довольно просто с регулярными выражениями. re.sub принимает функцию в качестве аргумента, которому передается объект сопоставления.

>>> import re
>>> s = 'hello <wolfrevokcats>, how <t uoy era>oday?'
>>> re.sub('<(.*?)>', lambda m: m.group(1)[::-1], s)
'hello stackru, how are you today?'

Объяснение регулярного выражения:

<(.*?)> будет соответствовать всем между < а также > в соответствующей группе 1. Чтобы убедиться, что двигатель регулярного выражения остановится на первом > вхождение символа, ленивый квантификатор *? используется.

Функция lambda m: m.group(1)[::-1] это передается re.sub берет объект соответствия, извлекает группу 1 и переворачивает строку. в заключение re.sub вставляет это возвращаемое значение.

Или используйте re.sub() и заменяющая функция:

>>> import re 
s = 'hello <wolfrevokcats>, how <t uoy era>oday?'
>>> re.sub(r"<(.*?)>", lambda match: match.group(1)[::-1], s)
'hello stackru, how are you today?'

где .*? будет соответствовать любым символам любое количество раз без жадного способа. Скобки вокруг него помогут нам зафиксировать его в группе, к которой мы затем будем обращаться в замещающей функции - match.group(1), [::-1] запись среза переворачивает строку.

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

content = "hello <wolfrevokcats>, how <t uoy era>oday?"

insert_pos = -1
result = []
placeholder_count = 0

for pos, ch in enumerate(content):
    if ch == '<':
        insert_pos = pos
    elif ch == '>':
        insert_pos = -1
        placeholder_count += 1
    elif insert_pos >= 0:
        result.insert(insert_pos - (placeholder_count * 2), ch)
    else:
        result.append(ch)

print("".join(result))

Суть кода состоит в том, чтобы иметь только один проход в строке по одному символу за раз. Когда вы выходите за скобки, просто добавьте символ в конец строки результата. Внутри скобок вставьте символ в положение открывающей скобки (то есть предварительно вставьте символ).

Я согласен с тем, что регулярные выражения являются подходящим инструментом для решения этой проблемы, и мне нравится суть ответа Дмитрия Б.. Тем не менее, я использовал этот вопрос на практике в отношении генераторов и функционального программирования, и я публикую свое решение только для того, чтобы поделиться им.

msg = "<,woN> hello <wolfrevokcats>, how <t uoy era>oday?"

def traverse(s, d=">"):
    for c in s:
        if c in "<>": d = c
        else: yield c, d

def group(tt, dc=None):
    for c, d in tt:
        if d != dc:
            if dc is not None:
                yield dc, l
            l = [c]
            dc = d
        else:
            l.append(c)
    else: yield dc, l

def direct(groups):
    func = lambda d: list if d == ">" else reversed
    fst = lambda t: t[0]
    snd = lambda t: t[1]
    for gr in groups:
        yield func(fst(gr))(snd(gr))

def concat(groups):
    return "".join("".join(gr) for gr in groups)

print(concat(direct(group(traverse(msg)))))

#Now, hello stackru, how are you today?

Вот еще один без использования регулярных выражений:

def reverse_marked(str0):
    separators = ['<', '>']
    reverse = 0
    str1 = ['', str0]
    res = ''

    while len(str1) == 2:
        str1 = str1[1].split(separators[reverse], maxsplit=1)
        res = ''.join((res, str1[0][::-1] if reverse else str1[0]))
        reverse = 1 - reverse  # toggle 0 - 1 - 0 ...
    return res

print(reverse_marked('hello <wolfrevokcats>, how <t uoy era>oday?'))

Вывод:

hello stackru, how are you today?
Другие вопросы по тегам