与a previous question相关,我正在尝试替换多个大型CSV文件。
列顺序(和内容)在文件之间发生变化,但是对于每个文件,我想要大约10列,并且可以通过列标题名称进行标识。我也想为每一列提供1-2个词典。因此,对于我想要的列,我只想使用正确的字典,并希望按顺序实现它们。
我试图解决这个问题的一个例子:
# -*- coding: utf-8 -*-
import re
# imaginary csv file. pretend that we do not know the column order.
Header = [u'col1', u'col2']
Line1 = [u'A',u'X']
Line2 = [u'B',u'Y']
fileLines = [Line1,Line2]
# dicts to translate lines
D1a = {u'A':u'a'}
D1b = {u'B':u'b'}
D2 = {u'X':u'x',u'Y':u'y'}
# dict to correspond header names with the correct dictionary.
# i would like the dictionaries to be read sequentially in col1.
refD = {u'col1':[D1a,D1b],u'col2':[D2]}
# clunky replace function
def freplace(str, dict):
rc = re.compile('|'.join(re.escape(k) for k in dict))
def trans(m):
return dict[m.group(0)]
return rc.sub(trans, str)
# get correspondence between dictionary and column
C = []
for i in range(len(Header)):
if Header[i] in refD:
C.append([refD[Header[i]],i])
# loop through lines and make replacements
for line in fileLines:
for i in range(len(line)):
for j in range(len(C)):
if C[j][1] == i:
for dict in C[j][0]:
line[i] = freplace(line[i], dict)
我的问题是这段代码很慢,我无法弄清楚如何加快速度。 我是初学者,我的猜测是我的freplace
函数在很大程度上减慢了速度,因为它必须为每一行中的每一列编译。我想从该函数中取出rc = re.compile('|'.join(re.escape(k) for k in dict))
行,但不知道如何做到这一点并仍然保留我的其余代码所做的事情。
答案 0 :(得分:3)
你可以做很多事情来加快速度:
首先,使用csv
模块。它为读取和写入CSV文件提供了高效且无错误的方法。特别是DictReader
对象是您感兴趣的对象:它将从文件中读取的每一行都显示为由其列名称键入的字典。
其次,编译你的正则表达式,而不是每次使用它们。将已编译的正则表达式保存在由您要应用它们的列键入的字典中。
第三,考虑如果你将一百个正则表达式应用于长字符串,那么你将从头到尾扫描字符串一百次。这可能不是解决问题的最佳方法;你可能最好花一些时间在一个让你从头到尾读取字符串的方法。
答案 1 :(得分:1)
您不需要re
:
# -*- coding: utf-8 -*-
# imaginary csv file. pretend that we do not know the column order.
Header = [u'col1', u'col2']
Line1 = [u'A',u'X']
Line2 = [u'B',u'Y']
fileLines = [Line1,Line2]
# dicts to translate lines
D1a = {u'A':u'a'}
D1b = {u'B':u'b'}
D2 = {u'X':u'x',u'Y':u'y'}
# dict to correspond header names with the correct dictionary
refD = {u'col1':[D1a,D1b],u'col2':[D2]}
# now let's have some fun...
for line in fileLines:
for i, (param, word) in enumerate(zip(Header, line)):
for minitranslator in refD[param]:
if word in minitranslator:
line[i] = minitranslator[word]
返回:
[[u'a', u'x'], [u'b', u'y']]
答案 2 :(得分:0)
所以如果是这样的话,并且所有10列每次都有相同的名称,但是不按顺序,(我不确定这是你在那里做的,但是这里有)保留一个数组标题名称,每个列分成一个元素(每行应该是10个项目),现在只需通过一个case / select组合来偏移正则表达式,比较标题数组的元素编号,然后在case中,引用数据数组在相同的偏移量,因为名称是正确的情况下你应该能够重复使用相同的10个正则表达式,而不必每次都重新编译一个新的“命令”。
我希望这是有道理的。对不起,我不知道帮助你的语法,但我希望我的想法是你正在寻找的 编辑: 即。
在开始循环之前初始化所有正则表达式。
然后在你读了一行之后(在标题行之后)
选择array [n]
案例“column1”
正则表达式(数据[0]);
案例“column2”
正则表达式(数据[1]); 。 。 。 。 结束选择
这应该为正确的列调用正确的正则表达式