反转字符串中标记的子字符串
Reverse marked substrings in a string
我有一个字符串,其中 <
和 >
中的每个标记子字符串
必须颠倒(括号不嵌套)。例如,
"hello <wolfrevokcats>, how <t uoy era>oday?"
应该变成
"hello Whosebug, how are you today?"
我目前的想法是遍历字符串并找到索引对
<
和 >
在哪里。然后只需将字符串切片并放入切片
再次与标记之间的所有内容一起反转。
这是正确的方法吗?有obvious/better解决方案吗?
或者,使用 re.sub()
和 替换函数:
>>> import re
s = 'hello <wolfrevokcats>, how <t uoy era>oday?'
>>> re.sub(r"<(.*?)>", lambda match: match.group(1)[::-1], s)
'hello Whosebug, how are you today?'
其中 .*?
将在 non-greedy fashion. The parenthesis around it would help us to capture it in a group which we then refer to in the replacing function - match.group(1)
. [::-1]
slice notation reverses a string.
中匹配任何字符任意次数
使用正则表达式非常简单。 re.sub
将函数作为匹配对象传递给的参数。
>>> import re
>>> s = 'hello <wolfrevokcats>, how <t uoy era>oday?'
>>> re.sub('<(.*?)>', lambda m: m.group(1)[::-1], s)
'hello Whosebug, how are you today?'
正则表达式的解释:
<(.*?)>
将匹配匹配组 1 中 <
和 >
之间的所有内容。为确保正则表达式引擎将在第一个 >
符号出现时停止,使用惰性量词 *?
。
传递给 re.sub
的函数 lambda m: m.group(1)[::-1]
获取匹配对象,提取第 1 组,并反转字符串。最后 re.sub
插入这个 return 值。
我假设这是一项课程作业,不允许使用正则表达式。所以我将提供一个不使用它的解决方案。
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))
代码的要点是一次只对字符串传递一个字符。在括号外时,只需将字符附加到结果字符串的末尾。在括号内时,在左括号的位置插入字符(即前置字符)。
我同意正则表达式是解决这个问题的合适工具,我喜欢 Dmitry B. 回答的要点。但是,我用这个问题来练习生成器和函数式编程,我post我的解决方案只是为了分享它。
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 Whosebug, 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 Whosebug, how are you today?
我有一个字符串,其中 <
和 >
中的每个标记子字符串
必须颠倒(括号不嵌套)。例如,
"hello <wolfrevokcats>, how <t uoy era>oday?"
应该变成
"hello Whosebug, how are you today?"
我目前的想法是遍历字符串并找到索引对
<
和 >
在哪里。然后只需将字符串切片并放入切片
再次与标记之间的所有内容一起反转。
这是正确的方法吗?有obvious/better解决方案吗?
或者,使用 re.sub()
和 替换函数:
>>> import re
s = 'hello <wolfrevokcats>, how <t uoy era>oday?'
>>> re.sub(r"<(.*?)>", lambda match: match.group(1)[::-1], s)
'hello Whosebug, how are you today?'
其中 .*?
将在 non-greedy fashion. The parenthesis around it would help us to capture it in a group which we then refer to in the replacing function - match.group(1)
. [::-1]
slice notation reverses a string.
使用正则表达式非常简单。 re.sub
将函数作为匹配对象传递给的参数。
>>> import re
>>> s = 'hello <wolfrevokcats>, how <t uoy era>oday?'
>>> re.sub('<(.*?)>', lambda m: m.group(1)[::-1], s)
'hello Whosebug, how are you today?'
正则表达式的解释:
<(.*?)>
将匹配匹配组 1 中 <
和 >
之间的所有内容。为确保正则表达式引擎将在第一个 >
符号出现时停止,使用惰性量词 *?
。
传递给 re.sub
的函数 lambda m: m.group(1)[::-1]
获取匹配对象,提取第 1 组,并反转字符串。最后 re.sub
插入这个 return 值。
我假设这是一项课程作业,不允许使用正则表达式。所以我将提供一个不使用它的解决方案。
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))
代码的要点是一次只对字符串传递一个字符。在括号外时,只需将字符附加到结果字符串的末尾。在括号内时,在左括号的位置插入字符(即前置字符)。
我同意正则表达式是解决这个问题的合适工具,我喜欢 Dmitry B. 回答的要点。但是,我用这个问题来练习生成器和函数式编程,我post我的解决方案只是为了分享它。
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 Whosebug, 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 Whosebug, how are you today?