提问人:user688486 提问时间:8/15/2023 更新时间:8/21/2023 访问量:97
直接通过“re.split”(在 Python 中)将每个相邻的不同数字之间的字符串分开?
Separate a string between each two neighbouring different digits via `re.split` DIRECTLY (in Python)?
问:
例如,我想转换为 .当然,这可以在不使用任何正则表达式的情况下在 for 循环中完成,但我想知道这是否可以通过单个正则表达式来完成。目前,我找到了两种方法:"91234 5g5567\t7₇89^"
["9","1","2","3","4 5g55","67\t7₇8","9^"]
>>> import re
>>> def way0(char: str):
... delimiter = ""
... while True:
... delimiter += " "
... if delimiter not in char:
... substitution = re.compile("([0-9])(?!\\1)([0-9])")
... replacement = "\\1"+delimiter+"\\2"
... cin = [char]
... while True:
... cout = []
... for term in cin: cout.extend(substitution.sub(replacement,term).split(delimiter))
... if cout == cin:
... return cin
... else:
... cin = cout
...
>>> way0("91234 5g5567\t7₇89^")
['9', '1', '2', '3', '4 5g55', '67\t7₇8', '9^']
>>> import functools
>>> way1 = lambda w: ["".join(list(y)) for x, y in itertools.groupby(re.split("(0+|1+|2+|3+|4+|5+|6+|7+|8+|9+)", w), lambda z: z != "") if x]
>>> way1("91234 5g5567\t7₇89^")
['9', '1', '2', '3', '4 5g55', '67\t7₇8', '9^']
然而,两者都不是简洁的(和理想的)。我已经阅读了 的帮助页面;遗憾的是,以下代码未返回所需的输出:way0
way1
re.split
>>> re.split(r"(\d)(?!\1)(\d)","91234 5g5567\t7₇89^")
['', '9', '1', '', '2', '3', '4 5g5', '5', '6', '7\t7₇', '8', '9', '^']
可以直接解决这个问题(即无需额外转换)吗?(请注意,这里我不关注效率。re.split
之前有一些关于这个主题的问题(例如,两位数不相同的两位数的正则表达式,匹配 2 位数字但不同的数字的正则表达式,以及匹配不相等或反转的数字集的正则表达式),但它们是关于“RegMatch”的。事实上,我的问题是关于“RegSplit”(而不是“RegMatch”或“RegReplace”)。
答:
如果您想在不捕获和任何进一步处理的情况下解决此问题,一个想法是仅使用环视,并在后方查看不允许两个相同的数字向前看。re.split
(?=[0-9])(?<=(?!00|11|22|33|44|55|66|77|88|99)[0-9])
请参阅 regex101 上的此演示或 tio.run 上的 Python 演示
它的工作方式是显而易见的。环视查找两位数之间的任何位置。在后面的看,如果前面有两个相同的数字,则在后面看,前视会阻止匹配(之前)。
我使用了而不是因为不确定 \d
是否与您的 Python 版本中的 unicode 数字匹配。[0-9]
\d
评论
\d
flags=re.A
您可以使用 re.finditer
和 re.findall
解决这个问题,尽管它有点复杂,因为负面前瞻需要捕获组(因为在其结果中返回捕获组的内容)。findall
findall
s ="91234 5g5567\t7₇89^"
# re.finditer
[m.group(0) for m in re.finditer(r'.*?(?:([0-9])(?=[0-9])(?!\1)|.$)', s)]
# re.findall
[t[0] for t in re.findall(r'(.*?(?:([0-9])(?=[0-9])(?!\2)|.$))', s)]
在这两种情况下,答案都是
['9', '1', '2', '3', '4 5g55', '67\t7₇8', '9^']
tio.run 上的 Python 演示
评论
re.sub(r“(?<=([0-9]))(?=[0-9])(?!\1)“,”-“,s).split(”-“)
re.split(r“(?=[0-9])(?<=(?!00|11|22|33|44|55|66|77|88|99)[0-9])“, s)
[m.group(0) for m in re.finditer(r'.*?(?:([0-9])(?=[0-9])(?!\1)|.$)', s)]
re.findall
[t[0] for t in re.findall(r'(.*?(?:([0-9])(?=[0-9])(?!\2)|.$))', s)]