【问题标题】:Merging three regex patterns used for text cleaning to improve efficiency合并用于文本清理的三个正则表达式模式以提高效率
【发布时间】:2020-11-20 15:15:11
【问题描述】:

给定一个文本,我想进行一些修改:

  1. 替换句首的大写字符。
  2. 删除' 等字符(不添加空格)
  3. 删除不需要的字符,例如 ³? , ! .(并替换为空格)
def multiple_replace(text):
    # first sub so words like can't will change to cant and not can t
    first_strip=re.sub("[’']",'',text) 
    def cap(match):
        return (match.group().lower())

    p = re.compile(r'((?<=[\.\?!]\s)(\w+)|(^\w+))')
    #second sub to change all words that begin a sentence to lowercase
    second_strip = p.sub(cap,first_strip) 
    # third_strip is to remove all . from text unless they are used in decimal numbers
    third_strip= re.sub(r'(?<!\d)\.|\.(?!\d)','',second_strip)
    # fourth strip to remove unexpected char that might be in text for example !,?³ and replace with whitespace
    forth_strip=re.sub('[^A-Za-z0-9@#_$&%]+',' ', third_strip)
    return forth_strip

我想知道是否有更有效的方法来做到这一点?因为我要检查文本 4 次,所以它可以采用正确的格式供我解析。这似乎很多,尤其是在有数百万个文档的情况下。有没有更有效的方法来做到这一点?

【问题讨论】:

  • 没有什么明显的想法,但这可能是一个 XY 问题,因为您提到您正在尝试“解析”某些东西。如果您显示输入的代表性 sn-p 以及您想要的最终输出以及您尝试实现的转换的解释,则可能有更好的方法可以完全避免这种特殊方法。
  • 解析的时间可能会超过“清理”文本的时间,在这种情况下,提高清理效率没有多大意义。 “过早的优化是编程中万恶(或至少是大部分)的根源。” -克努斯

标签: python regex parsing


【解决方案1】:

您可以使用交替来匹配字符串开头的大写字符 A-Z,或在 . ?! 后跟空格字符。

我认为您还可以将. 添加到否定字符类[^A-Za-z0-9@#_$&amp;%.]+ 以不删除十进制值的点并更改操作顺序以在删除任何点之前先使用cap

import re

def cap(match):
    return match.group().lower()


p = re.compile(r'(?<=[.?!]\s)[A-Z]|^[A-Z]', re.M)

text = "A test here. this `` (*)is. Test, but keep 1.2"
first_strip = p.sub(cap, text)
second_strip = re.sub(r"[`']+|(?<!\d)\.|\.(?!\d)", '', first_strip)
third_strip = re.sub('[^A-Za-z0-9@#_$&%.]+', ' ', second_strip)
print(third_strip)

输出

a test here this is test but keep 1.2

Python demo


您还可以使用包含所有 3 种模式和 2 个捕获组的 lambda,检查回调中的组值,但我认为这不会提高可读性或使其更容易更改或测试。

import re

p = re.compile(r"(?:((?<=[.?!]\s)[A-Z]|^[A-Z])|[`']+|((?<!\d)\.|\.(?!\d))|[^A-Za-z0-9@#_$&%.]+)", re.M)
text = "A test here. this `` (*)is. Test, but keep 1.2"
result = re.sub(p, lambda x: x.group(1).lower() if x.group(1) else ('' if x.group(2) else ' '), text)

print(result)

输出

a test here this is test but keep 1.2

Python demo

【讨论】:

  • re.M 是做什么的?无论如何,如果我的字符串包含“test y'all Towson take away”,那么它会将 y'all 拆分为 y all,因此当我将字符串拆分为两个不同的标记时,这就是为什么我需要它是 yall
  • 表示Multiline,图案中有一个锚点^
猜你喜欢
  • 1970-01-01
  • 2020-07-09
  • 1970-01-01
  • 1970-01-01
  • 2017-07-16
  • 2011-05-26
  • 1970-01-01
  • 2012-04-10
  • 2017-10-31
相关资源
最近更新 更多