更快的操作读取文件

时间:2014-08-15 01:09:39

标签: python text-files

我必须处理一个15MB的txt文件(核酸序列)并找到所有不同的子串(大小为5)。例如:

ABCDEF

会返回2,因为我们有ABCDE和BCDEF,但是

AAAAAA

将返回1.我的代码:

control_var = 0
f=open("input.txt","r")
list_of_substrings=[]
while(f.read(5)!=""):
    f.seek(control_var)
    aux = f.read(5)
    if(aux not in list_of_substrings):
        list_of_substrings.append(aux)
    control_var += 1
f.close()
print len(list_of_substrings)

另一种方法会更快(而不是直接比较文件中的字符串)吗?

4 个答案:

答案 0 :(得分:1)

15MB听起来不是很多。这样的事情可能会很好:

import Counter, re
contents = open('input.txt', 'r').read()
counter = Counter.Counter(re.findall('.{5}', contents))
print len(counter)

<强>更新

我认为user590028提供了一个很好的解决方案,但这是另一种选择:

contents = open('input.txt', 'r').read()
print set(contents[start:start+5] for start in range(0, len(contents) - 4))

# Or using a dictionary
# dict([(contents[start:start+5],True) for start in range(0, len(contents) - 4)]).keys()

答案 1 :(得分:1)

根据您对合法子字符串的定义,这是一个可能的解决方案:

import re

regex = re.compile(r'(?=(\w{5}))')
with open('input.txt', 'r') as fh:
    input = fh.read()
print len(set(re.findall(regex, input)))

当然,您可以将\w替换为您认为合适的任何内容,以符合子字符串中的合法字符。例如[A-Za-z0-9]将匹配所有字母数字字符。

这是一个执行示例:

>>> import re
>>> input = "ABCDEF GABCDEF"
>>> set(re.findall(regex, input))
set(['GABCD', 'ABCDE', 'BCDEF'])

编辑:根据上面的评论,文件中的所有字符都有效,不包括最后一个(\n),似乎没有真正需要定期这里的表达式和迭代方法要快得多。您可以使用此代码自行对其进行基准测试(请注意,我稍微修改了函数以反映有关有效子字符串定义的更新):

import timeit
import re

FILE_NAME = r'input.txt'

def re_approach():
    return len(set(re.findall(r'(?=(.{5}))', input[:-1])))

def iter_approach():
    return len(set([input[i:i+5] for i in xrange(len(input[:-6]))]))

with open(FILE_NAME, 'r') as fh:
    input = fh.read()

# verify that the output of both approaches is identicle
assert set(re.findall(r'(?=(.{5}))', input[:-1])) == set([input[i:i+5] for i in xrange(len(input[:-6]))])
print timeit.repeat(stmt = re_approach, number = 500)
print timeit.repeat(stmt = iter_approach, number = 500)

答案 2 :(得分:0)

您可以使用字典,其中每个键都是子字符串。它将处理重复,你可以在最后计算密钥。

所以:读一遍文件,将每个子字符串存储在字典中,这将处理查找重复的子字符串&amp;计算不同的。

答案 3 :(得分:0)

一次性读取更多i / o效率,并且使用dict()将比在列表中测试存在更快。类似的东西:

fives = {}
buf = open('input.txt').read()
for x in xrange(len(buf) - 4):
    key = buf[x:x+5]
    fives[key] = 1

for keys in fives.keys():
    print keys