使用递增数字序列的正则表达式 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
,它会在每次出现时分裂,因为每个数字都比最后一个大。
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
语句中有所不同,因此此逻辑完全可以根据您的需要进行定制。
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!']
假设我有一个字符串:
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
,它会在每次出现时分裂,因为每个数字都比最后一个大。
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
语句中有所不同,因此此逻辑完全可以根据您的需要进行定制。
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!']