Python加速从极大的字符串中检索数据

时间:2012-10-19 21:38:25

标签: python regex performance python-2.6 substitution

再见下:

我有一个列表,我转换为一个非常长的字符串,因为我正在尝试编辑它,因为你可以收集它叫做tempString。它现在起作用,只需要长时间操作,可能是因为它是几个不同的正则表达式。它们如下:

tempString = ','.join(str(n) for n in coords)
tempString = re.sub(',{2,6}', '_', tempString)
tempString = re.sub("[^0-9\-\.\_]", ",", tempString)
tempString = re.sub(',+', ',', tempString)
clean1 = re.findall(('[-+]?[0-9]*\.?[0-9]+,[-+]?[0-9]*\.?[0-9]+,'
                 '[-+]?[0-9]*\.?[0-9]+'), tempString)
tempString = '_'.join(str(n) for n in clean1)
tempString = re.sub(',', ' ', tempString)

基本上它是一个包含逗号的长字符串和大约1-5百万组4个浮点数/整数(两种可能的混合),:

-5.65500020981,6.88999986649,-0.454999923706,1,,,-5.65500020981,6.95499992371,-0.454999923706,1,,,

我不需要/想要的每一组中的第四个数字,我实际上只是试图将字符串拆分为一个列表,每个浮点数用空格隔开3个。

上面的代码完美无缺,但你可以想象在大字符串上耗费时间。

我已经在这里做了很多关于解决方案的研究,但它们似乎都是针对单词,即将一个单词换成另一个单词。


修改 好的,这是我正在使用的解决方案:

def getValues(s):
    output = []
    while s:
        # get the three values you want, discard the 3 commas, and the 
        # remainder of the string
        v1, v2, v3, _, _, _, s = s.split(',', 6)
        output.append("%s %s %s" % (v1.strip(), v2.strip(), v3.strip()))         
    return output
coords = getValues(tempString)

任何人都有任何建议可以加快速度吗?在运行一些测试后,它仍然需要比我希望的更长的时间。

我一直在看numPy,但我老实说完全不知道如何使用它,我明白在完成上述操作并清理了值之后我可以更有效地使用numPy,但是不确定NumPy如何适用于上述情况。

以上清理50k套需要大约20分钟,我无法想象它会在我的100万套完整的字符串中持续多长时间。令人惊讶的是,最初导出数据的程序在100万套

中只花了大约30秒

2 个答案:

答案 0 :(得分:2)

根据您的示例数据:

>>> s = "-5.65500020981,6.88999986649,-0.454999923706,1,,,-5.65500020981,6.95499992371,-0.454999923706,1,,,"
>>> def getValues(s):
...     output = []
...     while s:
...         # get the three values you want, discard the 3 commas, and the 
...         # remainder of the string
...         v1, v2, v3, _, _, _, s = s.split(',', 6)
...         output.append("%s %s %s" % (v1, v2, v3))
...         
...     return output
>>> getValues(s)
['-5.65500020981 6.88999986649 -0.454999923706', '-5.65500020981 6.95499992371 -0.454999923706']

...一旦你将这些解析后的值作为列表中的字符串,你可以做任何你需要做的事情。

或者如果您愿意,可以使用生成器,这样您就不需要一次构建整个返回字符串:

>>> def getValuesGen(s):
...     while s:
...         v1, v2, v3, _, _, _, s = s.split(',', 6)
...         yield "%s %s %s" % (v1, v2, v3)
>>> for v in getValuesGen(s):
...     print v
...     
... 
-5.65500020981 6.88999986649 -0.454999923706
-5.65500020981 6.95499992371 -0.454999923706

您可能还想尝试一种在,,,逗号集上预分割长列表的方法,而不是不断构建和处理一组较短的字符串,例如:

>>> def getValues(s):
...     # split your long string into a list of chunked strings
...     strList = s.split(",,,")
...     for chunk in strList:
...         if chunk:
...         # ...then just parse apart each individual set of data values
...             vals = chunk.split(',')
...             yield "%s %s %s" % (vals[0], vals[1], vals[2])
>>> for v in getValues(s10):
...     print v
-5.1  6.8  -0.454
-5.1  6.8  -0.454
-5.1  6.8  -0.454
-5.1  6.8  -0.454
-5.1  6.8  -0.454
-5.1  6.8  -0.454
-5.1  6.8  -0.454
-5.1  6.8  -0.454
-5.1  6.8  -0.454
-5.1  6.8  -0.454

在某些时候,当您处理这样的大型数据集并且遇到速度问题时,将事情简化为在C中进行艰苦工作的模块(如NumPy)就开始变得有意义了。

答案 1 :(得分:0)

减少内存消耗而不必更改正则表达式中的任何内容的一种方法是使用re.finditer()方法而不是re.findall()。这将逐个遍历值,而不是将整个字符串读入单个列表对象。 http://docs.python.org/library/re.html#re.finditer