使用递增数字序列的正则表达式 Python

Regex using increasing sequence of numbers Python

假设我有一个字符串:

teststring =  "1.3 Hello how are you 1.4 I am fine, thanks 1.2 Hi There 1.5 Great!" 

我想作为:

testlist = ["1.3 Hello how are you", "1.4 I am fine, thanks 1.2 Hi There", "1.5 Great!"]

基本上,仅在差异为 .1(即 1.2 到 1.3)的递增数字上拆分。

有没有办法用正则表达式拆分它,但只捕获递增的序列号?我在 python 中编写了代码,为每个代码使用自定义 re.compile() 顺序迭代,这没问题,但非常笨拙。

类似这样的东西(其中 parts1_temp 是 x.x. 字符串中数字的给定列表):

parts1_temp = ['1.3','1.4','1.2','1.5']
parts_num =  range(int(parts1_temp.split('.')[1]), int(parts1_temp.split('.')[1])+30)
parts_search = ['.'.join([parts1_temp.split('.')[0], str(parts_num_el)]) for parts_num_el in parts_num]
#parts_search should be ['1.3','1.4','1.5',...,'1.32']

for k in range(len(parts_search)-1):
    rxtemp = re.compile(r"(?:"+str(parts_search[k])+")([\s\S]*?)(?=(?:"+str(parts_search[k+1])+"))", re.MULTILINE)
    parts_fin = [match.group(0) for match in rxtemp.finditer(teststring)]

可是人就是丑啊。有没有办法在正则表达式中更直接地做到这一点?我想这是有人在某个时候想要使用正则表达式的功能,但我找不到任何关于如何解决这个问题的想法(也许纯正则表达式是不可能的)。

此方法使用 finditer 找到 \d+\.\d+ 的所有位置,然后测试匹配是否在数值上大于前一个。如果测试为真,它将索引附加到 indices 数组。

最后一行使用取自 的列表推导式在给定的索引上拆分字符串。

原始方法

此方法确保上一个匹配项小于当前匹配项。这不是按顺序工作的,而是根据数字大小工作的。所以假设一个字符串有数字 1.1, 1.2, 1.4,它会在每次出现时分裂,因为每个数字都比最后一个大。

See code in use here

import re

indices = []
string =  "1.3 Hello how are you 1.4 I am fine, thanks 1.2 Hi There 1.5 Great!"
regex = re.compile(r"\d+\.\d+")
lastFloat = 0

for m in regex.finditer(string):
    x = float(m.group())
    if lastFloat < x:
        lastFloat = x
        indices.append(m.start(0))

print([string[i:j] for i,j in zip(indices, indices[1:]+[None])])

输出:['1.3 Hello how are you ', '1.4 I am fine, thanks 1.2 Hi There ', '1.5 Great!']


编辑

顺序法

此方法与原始方法非常相似,但是,在 1.1, 1.2, 1.4 的情况下,它不会在 1.4 上拆分,因为在给定 [=19= 的情况下它不会按顺序进行] 顺序分隔符。

下面的方法仅在 if 语句中有所不同,因此此逻辑完全可以根据您的需要进行定制。

See code in use here

import re

indices = []
string =  "1.3 Hello how are you 1.4 I am fine, thanks 1.2 Hi There 1.5 Great!"
regex = re.compile(r"\d+\.\d+")
lastFloat = 0

for m in regex.finditer(string):
    x = float(m.group())
    if (lastFloat == 0) or (x == round(lastFloat + .1, 1)):
        lastFloat = x
        indices.append(m.start(0))

print([string[i:j] for i,j in zip(indices, indices[1:]+[None])])

仅使用正则表达式 执行此操作似乎过于复杂。这个处理怎么样:

import re

teststring =  "1.3 Hello how are you 1.4 I am fine, thanks 1.2 Hi There 1.5 Great!" 
res = []
expected = None
for s in re.findall(r'\d+(?:\.\d+)?|\D+', teststring):
    if s[0].isdigit() and expected is None:
        expected = s
        fmt = '{0:.' + str(max(0, len(s) - (s+'.').find('.') - 1)) + 'f}'
        inc = float(re.sub(r'\d', '0', s)[0:-1] + '1')
    if s == expected:
        res.append(s)
        expected = fmt.format(float(s) + inc)
    elif expected:
        res[-1] = res[-1] + s

print (res)

如果数字恰好有两位或更多位小数,或者 none。

,这也适用

您还可以改变字符串,以便在数字旁边放置一个标记(如果它是递增序列的一部分)。然后,您可以在该标记处拆分:

import re
teststring =  "1.3 Hello how are you 1.4 I am fine, thanks 1.2 Hi There 1.5 Great!" 
numbers = re.findall('[\.\d]+', teststring)
final_string = re.sub('[\.\d]+', '{}', teststring).format(*[numbers[0]]+[numbers[i] if numbers[i] < numbers[i-1] else '*'+numbers[i] for i in range(1, len(numbers))]).split(' *')

输出:

['1.3 Hello how are you', '1.4 I am fine, thanks 1.2 Hi There', '1.5 Great!']