如何将多模式字符串高效拆分至统一格式字段
问题
我有一组遵循以下几种模式的字符串(其中每个no.为不同数值,可能包含科学计数法):
no.1 <= some text = no.2 <= no.3 some text = no.4 no.5 <= some text = no.6 some text = no.7 <= no.8
这些字符串的共性是包含<=和=符号的组合。我需要将这些字符串拆分,在数值缺失的位置填充None(或np.nan),最终每个字符串生成四个值:一个文本值,三个数值(缺失则为None),示例如下:
no.1 <= some text = no.2 <= no.3 -> [no.1, some text, no.2, no.3] some text = no.4 -> [None, some text, no.4, None] no.5 <= some text = no.6 -> [no.5, some text, no.6, None] some text = no.7 <= no.8 -> [None, some text, no.7, no.8]
用split()按'<='或'='拆分无法明确模式,当前用大量if-else条件实现但不够优雅:
lines = [ "0.5 <= First variable = 0.6 <= 1.5", "Second variable = 0.483983", "0.05 <= Third variable = 0.14897", "Fourth variable = 0.1 <= 1" ] outlines = [] for line in lines: out = [] if '=' in line.split('<=')[0]: out.append(None) out.append(line.split('<=')[0].split('=')[0]) out.append(line.split('<=')[0].split('=')[1]) else: out.append(line.split('<=')[0]) out.append(line.split('<=')[1].split('=')[0]) out.append(line.split('<=')[1].split('=')[1]) if '=' in line.split('<=')[-1]: out.append(None) else: out.append(line.split('<=')[-1]) outlines.append(out) outlines # 输出: # [['0.5 ', ' First variable ', ' 0.6 ', ' 1.5'], # [None, 'Second variable ', ' 0.483983', None], # ['0.05 ', ' Third variable ', ' 0.14897', None], # [None, 'Fourth variable ', ' 0.1 ', ' 1']]
请问有没有更简洁的实现方式?是否使用正则表达式均可?
解决方案
方法一:正则表达式(精准匹配)
用正则表达式一次性捕获所有可能的分组,直接对应目标输出的四个位置,缺失的分组自动替换为None,同时可以顺便去除多余空格:
import re # 定义匹配所有模式的正则表达式 pattern = re.compile(r'^(?:(\S+)\s*<=)?\s*(.+?)\s*=\s*(\S+?)(?:\s*<=(\S+))?$') lines = [ "0.5 <= First variable = 0.6 <= 1.5", "Second variable = 0.483983", "0.05 <= Third variable = 0.14897", "Fourth variable = 0.1 <= 1" ] result = [] for line in lines: match = pattern.fullmatch(line) # 处理每个捕获组,空值替换为None,同时去除首尾空格 left_num = match.group(1).strip() if match.group(1) else None text = match.group(2).strip() mid_num = match.group(3).strip() if match.group(3) else None right_num = match.group(4).strip() if match.group(4) else None result.append([left_num, text, mid_num, right_num]) print(result)
输出结果:
[['0.5', 'First variable', '0.6', '1.5'], [None, 'Second variable', '0.483983', None], ['0.05', 'Third variable', '0.14897', None], [None, 'Fourth variable', '0.1', '1']]
正则表达式说明:
^(?:(\S+)\s*<=)?:匹配开头可选的左数值,(\S+)捕获数值(非空白字符),\s*<=匹配空格和<=,?表示该部分可选\s*(.+?)\s*=:非贪婪匹配文本部分,前后\s*忽略多余空格\s*(\S+?):捕获中间数值(?:\s*<=(\S+))?$:匹配结尾可选的右数值部分,$确保匹配到行尾
方法二:统一分隔符后拆分(无需正则)
先把所有<=替换成=,将字符串统一用=拆分,再根据拆分后的部分长度和内容类型填充None:
lines = [ "0.5 <= First variable = 0.6 <= 1.5", "Second variable = 0.483983", "0.05 <= Third variable = 0.14897", "Fourth variable = 0.1 <= 1" ] result = [] for line in lines: # 替换<=为=,按=拆分后去除空字符串和首尾空格 parts = [p.strip() for p in line.replace('<=', '=').split('=') if p.strip()] # 根据parts长度判断模式并填充结果 if len(parts) == 2: res = [None, parts[0], parts[1], None] elif len(parts) == 3: # 判断第一个元素是否为数值(简单用float转换验证) try: float(parts[0]) res = [parts[0], parts[1], parts[2], None] except ValueError: res = [None, parts[0], parts[1], parts[2]] elif len(parts) == 4: res = [parts[0], parts[1], parts[2], parts[3]] result.append(res) print(result)
输出结果和方法一完全一致,这种方法更直观,适合对正则不熟悉的场景。
内容的提问来源于stack exchange,提问作者TY Lim
相关产品推荐
相关产品推荐

