[英]Python re.sub() optimization
我有一个python列表,每个字符串是以下4个可能的选项之一(当然名称会有所不同):
Mr: Smith\n
Mr: Smith; John\n
Smith\n
Smith; John\n
我希望这些更正为:
Mr,Smith,fname\n
Mr,Smith,John\n
title,Smith,fname\n
title,Smith,John\n
使用4 re.sub()很容易:
with open ("path/to/file",'r') as fileset:
dataset = fileset.readlines()
for item in dataset:
dataset = [item.strip() for item in dataset] #removes some misc. white noise
item = re.sub((.*):\W(.*);\W,r'\g<1>'+','+r'\g<2>'+',',item)
item = re.sub((.*);\W(.*),'title,'+r'\g<1>'+','+r'\g<2>',item)
item = re.sub((.*):\W(.*),r'\g<1>'+','+r'\g<2>'+',fname',item)
item = re.sub((*.),'title,'+r'\g<1>'+',fname',item)
虽然这对我正在使用的数据集很好,但我希望更有效率。
是否有单一操作可以简化此过程?
请原谅我忘了引用或其他一些; 我现在不在我的工作站,我知道我已经删除了换行符( \\n
)。
谢谢,
您可以将其减少到一行,而不是运行两个循环。 改编自如何在Python中迭代文件 (并使用我的代码部分中的代码 ):
f = open("path/to/file",'r')
while True:
x = f.readline()
if not x: break
print re.sub(r, repl, x)
请参阅Python - 如何在Python中逐行使用regexp,以获取其他替代方案。
为了便于查看,我已将文件更改为数组。
^(?:([^:\r\n]+):\W*)?([^;\r\n]+)(?:;\W*(.+))?
注意:你不需要python中的所有内容,为了在regex101上显示它,所以你的正则表达式实际上只是^(?:([^:]+):\\W*)?([^;]+)(?:;\\W*(.+))?
import re
a = [
"Mr: Smith",
"Mr: Smith; John",
"Smith",
"Smith; John"
]
r = r"^(?:([^:]+):\W*)?([^;]+)(?:;\W*(.+))?"
def repl(m):
return (m.group(1) or "title" ) + "," + m.group(2) + "," + (m.group(3) or "fname")
for s in a:
print re.sub(r, repl, s)
^
在行的开头断言位置 (?:([^:]+):\\W*)?
可选择匹配以下内容
([^:]+)
捕获任何字符,除了:
一次或多次进入捕获组1 :
字面意思匹配 \\W*
匹配任意数量的非单词字符(从OP的原始代码复制,我假设可以使用\\s*
代替) ([^;]+)
分组除以外的任何字符;
一次或多次进入捕获组2 (?:;\\W*(.+))?
可选择匹配以下内容
;
按字面意思匹配 \\W*
匹配任意数量的非单词字符(从OP的原始代码复制,我假设可以使用\\s*
代替) (.+)
任何字符捕获一次或多次到捕获组3中 鉴于正则表达式部分的上述解释。 re.sub(r, repl, s)
工作原理如下:
repl
是对repl
函数的回调,它返回:
group 1
如果它捕获任何东西,否则title
group 2
(它应该总是设置 - 再次使用OP的逻辑) group 3
如果它捕获任何东西, fname
否则 恕我直言,RegEx在这里太复杂了,你可以使用经典的字符串函数来分割你的字符串项目 。 为此,您可以使用partition
(或rpartition
)。
首先,将您的项目字符串拆分为“记录”,如下所示:
item = "Mr: Smith\n Mr: Smith; John\n Smith\n Smith; John\n"
records = item.splitlines()
# -> ['Mr,Smith,fname', 'Mr,Smith,John', 'title,Smith,fname', 'title,Smith,John']
然后,您可以创建一个简短的函数来规范化每个“记录”。 这是一个例子:
def normalize_record(record):
# type: (str) -> str
name, _, fname = record.partition(';')
title, _, name = name.rpartition(':')
title = title.strip() or 'title'
name = name.strip()
fname = fname.strip() or 'fname'
return "{0},{1},{2}".format(title, name, fname)
此函数比RegEx集合更容易理解。 而且,在大多数情况下,它更快。
为了更好地集成,您可以定义另一个函数来处理每个项目 :
def normalize(row):
records = row.splitlines()
return "\n".join(normalize_record(record) for record in records) + "\n"
演示:
item = "Mr: Smith\n Mr: Smith; John\n Smith\n Smith; John\n"
item = normalize(item)
你得到:
'Mr,Smith,fname\nMr,Smith,John\ntitle,Smith,fname\ntitle,Smith,John\n'
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.