将所有数值替换为格式化字符串

2024-06-01 13:37:05 发布

您现在位置:Python中文网/ 问答频道 /正文

我想做的是:

找出字符串中的所有数值。你知道吗

input_string = "高露潔光感白輕悅薄荷牙膏100   79.80"

numbers = re.finditer(r'[-+]?[0-9]*\.?[0-9]+(?:[eE][-+]?[0-9]+)?',input_string)

for number in numbers:
    print ("{}    start > {}, end > {}".format(number.group(), number.start(0), number.end(0)))

'''Output'''
>>100    start > 12, end > 15
>>79.80    start > 18, end > 23

然后我想把所有的整数和浮点值替换成某种格式:

INT_(number of digit)FLT(number of decimal places)

例如100 -> INT_3 // 79.80 -> FLT_2

因此,expect输出字符串如下所示:

"高露潔光感白輕悅薄荷牙膏INT_3   FLT2"

但是Python中的string replace substring方法有点奇怪,它不能存档我想做的事情。你知道吗

所以我尝试使用substring-append-substring方法

string[:number.start(0)] + "INT_%s"%len(number.group()) +.....

这看起来很愚蠢,而且最重要的是我仍然不能让它工作。你知道吗

有人能就这个问题给我一些建议吗?你知道吗


Tags: of方法字符串numberinputstringgroupsubstring
3条回答

你需要把正则表达式的各个部分像这样分组

import re

def repl(m):
    if m.group(1) is None: #int
        return ("INT_%i"%len(m.group(2)))        
    else: #float
        return ("FLT_%i"%(len(m.group(2))))

input_string = "高露潔光感白輕悅薄荷牙膏100   79.80"

numbers = re.sub(r'[-+]?([0-9]*\.)?([0-9]+)([eE][-+]?[0-9]+)?',repl,input_string)        

print(numbers)
  • 组0是匹配的整个字符串(可用于放入floatint
  • 组1是.之前的任何数字,如果.本身存在,则它是None
  • 组2是.后面的所有数字,如果它存在,否则它就是所有数字
  • 组3是指数部分,如果存在else None

你可以从中得到一个python数字

def parse(m):
    s=m.group(0)
    if m.group(1) is not None or m.group(3) is not None: # if there is a dot or an exponential part it must be a float
        return float(s)
    else:
        return int(s)

您可能正在寻找下面的代码(当然还有其他方法)。这一个只是从你正在做的事情开始,并展示如何做到这一点。你知道吗

import re
input_string = u"高露潔光感白輕悅薄荷牙膏100   79.80"

numbers = re.finditer(r'[-+]?[0-9]*\.?[0-9]+(?:[eE][-+]?[0-9]+)?',input_string)

s = input_string
for m in list(numbers)[::-1]:
    num = m.group(0)
    if '.' in num:
        s = "%sFLT_%s%s" % (s[:m.start(0)],str(len(num)-num.index('.')-1),s[m.end(0):])
    else:
        s = "%sINT_%s%s" % (s[:m.start(0)],str(len(num)), s[m.end(0):])
print(s)

这看起来可能有点复杂,因为确实有几个简单的问题需要解决。你知道吗

例如,您最初的正则表达式会同时找到int和float,但是您需要在之后应用完全不同的替换。如果你一次只做一件事,这会更简单。但是,由于float的某些部分可能看起来像int,一次执行所有操作可能不是一个坏主意,您只需了解这将导致二次检查来区分这两种情况。你知道吗

另一个更基本的问题是,实际上您不能替换python字符串中的任何内容。Python字符串是不可修改的对象,因此您必须创建一个副本。无论如何,这是好的,因为格式更改可能需要插入或删除字符,而就地替换将没有效率。你知道吗

最后一个需要考虑的问题是,替换必须向后进行,因为如果更改字符串的开头,匹配位置也会更改,下一个替换将不在正确的位置。如果我们向后做,一切都好。你知道吗

当然,我同意使用re.sub()要简单得多。你知道吗

使用re.sub和内部的回调方法,可以对匹配项执行各种操作:

import re
def repl(match):
    chunks = match.group(1).split(".")
    if len(chunks) == 2:
        return "FLT_{}".format(len(chunks[1]))
    else:
        return "INT_{}".format(len(chunks[0]))

input_string = "高露潔光感白輕悅薄荷牙膏100   79.80"
result = re.sub(r'[-+]?([0-9]*\.?[0-9]+)(?:[eE][-+]?[0-9]+)?',repl,input_string)
print(result)

参见Python demo

详细信息:

  • regex现在在数字部分(([0-9]*\.?[0-9]+))上有一个捕获组,这将在repl方法中进行分析
  • repl方法中,第1组内容被.拆分,以查看是否有浮点/双精度,如果是,则返回小数部分的长度,否则返回整数的长度。你知道吗

相关问题 更多 >