2

我有一个字符串,其中每个标记的子字符串<> 必须反转(括号不嵌套)。例如,

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

应该成为

 "hello stackoverflow, how are you today?"

我目前的想法是遍历字符串并找到成对的索引 where<>are。然后只需将字符串切片并将切片再次放在一起,标记之间的所有内容都颠倒过来。这是一个正确的方法吗?有明显/更好的解决方案吗?

4

5 回答 5

8

使用正则表达式非常简单。re.sub将函数作为参数传递给匹配对象。

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

正则表达式的解释:

<(.*?)>将匹配匹配组 1 之间的所有内容<>为确保正则表达式引擎将在第一个>符号出现时停止,使用惰性量词*?

lambda m: m.group(1)[::-1]传递给的函数re.sub获取匹配对象,提取组 1,并反转字符串。最后re.sub插入这个返回值。

于 2016-03-18T20:05:36.910 回答
4

或者,使用re.sub()替换功能

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

where会以非贪婪.*?的方式多次匹配任何字符。它周围的括号将帮助我们将它捕获在一个中,然后我们在替换函数中引用它 - 。切片表示法反转字符串match.group(1)[::-1]

于 2016-03-18T20:05:20.320 回答
3

我将假设这是一项课程作业,并且不允许使用正则表达式。所以我将提供一个不使用它的解决方案。

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))

代码的要点是一次只对字符串一个字符进行一次传递。在括号外时,只需将字符附加到结果字符串的末尾即可。在括号内时,在左括号的位置插入字符(即在字符前添加)。

于 2016-03-18T20:14:41.743 回答
0

我同意正则表达式是解决这个问题的合适工具,我喜欢 Dmitry B. 的答案的要点。但是,我用这个问题来练习生成器和函数式编程,我发布我的解决方案只是为了分享它。

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 stackoverflow, how are you today?
于 2016-03-19T02:17:15.973 回答
0

这是另一个不使用正则表达式的:

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 stackoverflow, how are you today?
于 2020-10-20T22:03:13.310 回答