我试图在每个3.1415926535897932384626433832795028841971
或0
组之后立即拆分任何数字字符串,例如0
。但是,我想在每组之后保持0。
例如,字符串10203040506070809011
应拆分为
['10', '20', '30', '40', '50', '60', '70', '80', '90', '11']
并且字符串3.1415926535897932384626433832795028841971
应该分成
['3.14159265358979323846264338327950', '28841971']
我尝试将字符串拆分为正后观和空字符串:
import re
p = '(?<=0+)'
re.search(p, '102030405')
><_sre.SRE_Match object; span=(2, 2), match=''>
'102030405'.split(p)
>['102030405']
但这根本不会拆分字符串,即使模式匹配。
我还尝试根据0
拆分字符串,并在前几个字符串后添加0
,但它似乎错综复杂且效率低下。
l = '102030405'.split('0')
[e+'0' for e in l[:-1]] + [l[-1]]
>['10', '20', '30', '40', '5']
有没有办法根据空字符串的前瞻或后看来分割字符串?我询问一般情况,而不仅仅是数字。例如,如果我想将3:18am5:19pm10:28am
拆分为不同时间而不会丢失am
或pm
,并获得数组['3:18am', '5:19pm', '10:28am']
,我将如何进行此操作?
答案 0 :(得分:1)
使用re.findall
:
l = re.findall(r'(?<![^0])[1-9.]+0*', s)
关键是要使用双重否定:不在和之前,不是零(匹配前面的零或字符串的开头)
答案 1 :(得分:1)
Python split
需要非零宽度匹配。
您可以使用findall
与此正则表达式来获取匹配项:
>>> print re.findall(r'([\d.]+?(?:0+|$))', '10203040506070809011')
['10', '20', '30', '40', '50', '60', '70', '80', '90', '11']
>>> print re.findall(r'([\d.]+?(?:0+|$))', '3.1415926535897932384626433832795028841971')
['3.14159265358979323846264338327950', '28841971']
([\d.]+?(?:0|$))
匹配以0
或行尾结尾的数字或点。
<强>更新强>
但是,我从您编辑过的问题和评论中注意到,您正在寻找通用解决方案,以便使用零宽度正则表达式进行拆分操作。
我建议你在python中安装非常有用的regex module。此模块的第1版提供了大多数PCRE功能,远远超过了默认的re
模块。
安装非常简单。只需从上面的链接下载tar gzip文件,然后运行:
sudo python setup.py install
从解压缩tar文件后获取的目录内部。 (在安装过程中忽略一些警告)。
安装regex
后,只需使用以下代码:
>>> import regex
>>> regex.DEFAULT_VERSION = regex.VERSION1
>>> regex.split(r'(?<=[ap]m)(?=.)', '3:18am5:19pm10:28am')
['3:18am', '5:19pm', '10:28am']
>>> print regex.split(r'(?<=0)(?=[1-9])', '10203040506070809011')
['10', '20', '30', '40', '50', '60', '70', '80', '90', '11']
>>> print regex.split(r'(?<=0)(?=[1-9])', '3.1415926535897932384626433832795028841971')
['3.14159265358979323846264338327950', '28841971']
>>> print regex.split(r'(?<=0)(?=[1-9])', '10020')
['100', '20']
答案 2 :(得分:1)
re.findall
中的这个简单正则表达式就足够了:
l = re.findall(r'[.1-9]+(?:0+|$)', s)
注意:
findall
会在字符串中返回所有非重叠匹配,作为字符串 。
对于每个匹配,我们希望最长的数字串(或点)以至少一个零结尾,或者字符串的结尾
最后的零不应该被捕获为另一个匹配(因此(?:...
)
同样适合你的第二个例子:
>>> re.findall(r'[\d:]+(?:am|pm|$)', '3:18am5:19pm10:28am')
['3:18am', '5:19pm', '10:28am']
无需前瞻/后视魔法或非贪婪匹配。
答案 3 :(得分:0)
阿努巴瓦的回答是对的。但是需要安装regex模块,不需要。
import re
pattern = r"(?<=0)(?=[1-9])"
s = "3.1415926535897932384626433832795028841971"
s2 = "10203040506070809011"
re.split(pattern, s)
# ['3.14159265358979323846264338327950', '28841971']
re.split(pattern, s2)
# ['10', '20', '30', '40', '50', '60', '70', '80', '90', '11']
您应该查看 re 模块页面以获取有关前瞻和后瞻的更多详细信息。 如果我要解释的话。我会说
(?<=...) 表示分隔符之前的内容。
(?=...) 表示分隔符之后的内容。
因此,(?<=0)(?=[1-9]) 表示在分隔符之前,这是空的,应该有一个零,而在它之后应该有一个 1 到 9。
regex 和 re 的速度比较。
表达 | 时间 |
---|---|
re.split(r"(?<=0)(?=[1-9])", s) |
5.78 纳秒 ± 0.103 纳秒 |
regex.split(r"(?<=0)(?=[1-9])", s) |
6.04 纳秒 ± 0.364 纳秒 |
re.split(r"(?<=0)(?=[1-9])", s2) |
5.83 纳秒 ± 0.061 纳秒 |
regex.split(r"(?<=0)(?=[1-9])", s2) |
6.34 纳秒 ± 1.16 纳秒 |