如何避免多重负前瞻的正则灾难性回溯及Pandas字符串处理
Pandas字符串条件添加与排除处理
需求
当DataFrame的Ruling列字符串满足以下条件时,在末尾添加section 22:
- 字符串包含
personal information - 字符串不包含
s. 26、s. 29、s. 33、s. 22、s. 32中的任意一项
示例数据
import pandas as pd df = pd.DataFrame({ 'Order': ['Order90-098','OrderF14-47', 'OrderF13-43', 'Order56-090', 'Order90-098', 'Order78-897'], 'Ruling': ['foo','personal information', 's. 26 personal information', 'personal information s. 33', 'personal information s. 67', 'personal s. 32 information']})
期望结果
df = pd.DataFrame({ 'Order': ['Order90-098','OrderF14-47', 'OrderF13-43', 'Order56-090', 'Order90-098', 'Order78-897'], 'Ruling': ['foo','personal information section 22', 's. 26 personal information', 'personal information s. 33', 'personal information s. 67 section 22', 'personal s. 32 information']})
问题分析
你之前尝试的多重负前瞻正则因结构冗余导致灾难性回溯,而析取式写法未覆盖全局匹配逻辑,导致排除条件失效。
解决方案
方案1:修正正则表达式
将所有排除项整合到单个负前瞻中,确保检查整个字符串是否包含任何排除项,同时精准匹配目标内容:
import re df['Ruling'] = df['Ruling'].apply( lambda x: re.sub( r'^(?!.*(s\. (?:22|26|29|32|33))).*(personal information.*)$', r'\1 section 22', x, flags=re.IGNORECASE ) )
^(?!.*(s\. (?:22|26|29|32|33))):负前瞻规则,确保字符串中不存在任何指定的s. xx项(personal information.*)$:捕获包含personal information的完整内容,用于替换时追加后缀
方案2:Pandas条件判断(可读性更强)
避开正则复杂度,直接用Python字符串判断结合Pandasapply实现,逻辑更直观:
exclude_terms = {'s. 26', 's. 29', 's. 33', 's. 22', 's. 32'} def add_section(text): if 'personal information' in text: # 检查是否存在任何排除项 if not any(term in text for term in exclude_terms): return text + ' section 22' return text df['Ruling'] = df['Ruling'].apply(add_section)
这种方法无需处理正则匹配的边界问题,代码维护成本更低。
内容的提问来源于stack exchange,提问作者oymonk
相关产品推荐
相关产品推荐

