我有一个非常大的文件,包含许多行和行。为了简化我的问题,我们假设有201列。第一列与AB:CD:EF:GH
类似,其他列与1:2:3:4
类似。正如所见,分隔符是相同的。所有列的模式应该是相同的。如果第一列有3个分隔符,则表示给定行中的所有其他分隔符有3个分隔符。
例如,我想知道该行第一列中EF
的索引,并使用该索引从所有列中获取3
。 EF
的索引在各行各不相同。
我使用了两种拆分方法。但是,由于我的文件很大,它会为我的代码带来很大的瓶颈。顺便说一下,有超过一千万行。
with open("amkhepinizin.txt", "r") as theFile:
for line in theFile:
ind = line[0].split(":").index("EF")
theList = []
for j in range(1,202):
theList.append(line[j].split(":")[ind])
foo(theList) # some processes
它有效,但有点慢。我发现每行调用大约200次的拆分方法会导致代码运行缓慢。我认为我可以通过使用正则表达式来解决这个问题,我一开始并不知道。我试图找出如何使用正则表达式,但我不能。
这是我文件的一个小例子。
EF:AD:DP:GQ:PL 0/0:95,0:96:99:0,214,2836 0/1:103,0:103:99:0,229,3036
AD:EF:DP:GQ:PL 0/1:16,7:25:99:242:5,1,6 0/0:32,0:33:93:0,93,1102
DP:GQ:EF 99:533,0,422:1 99:310,0,1129:6
::EF:DP: :::: 0::0::
基本上,我想从第一行获得0/0
和0/1
;然后来自第二行的16,7
和32,0
以及来自第三行的1
和6
。来自第四行的""
和0
。
你能帮我解决一下如何在我的代码中实现正则表达式。
如果您认为正则表达式没有加强我的代码,我会很感激其他建议。
答案 0 :(得分:0)
它可能会加快您的代码使用某些生成器:
import re
data = """
EF:AD:DP:GQ:PL 0/0:95,0:96:99:0,214,2836 0/1:103,0:103:99:0,229,3036
AD:EF:DP:GQ:PL 0/1:16,7:25:99:242:5,1,6 0/0:32,0:33:93:0,93,1102
DP:GQ:EF 26:99:533,0,422:1 39:99:310,0,1129:6
::EF:DP: :::: 0::0::
"""
rx_needle = 'EF'
rx_lines = re.compile(r'.+')
rx_split = re.compile(r'\s{2,}')
def item_getter(line, needle):
parts = rx_split.split(line)
try:
ind = parts[0].split(':').index(needle)
values = (p[ind] for part in parts[1:] for p in [part.split(':')])
return values
except ValueError:
return None
for line in rx_lines.finditer(data):
values = item_getter(line.group(0), rx_needle)
# do whatever you want to do with values here
print(list(values))
这里的想法是使用生成器来查找re.finditer()
的下一行,并使用另一个生成器从该行获取特定值(给定针被找到)。
优点是你可以在将来的某个特定时间停止(让我们说在1000行之后),并且只使用少量(呃)的内存。
def t():
for line in rx_lines.finditer(data):
values = item_getter(line.group(0), rx_needle)
import timeit
s = timeit.timeit(t, number=10**5)
print(s)
# 3.28 s
因此,要对400k行运行该函数,大约需要3秒钟。