2013-06-08 2 views
3

하나의 파일에서 다른 행의 값을 검색하고 있습니다. 정확한 값은 검색 파일에서 한 번만 발생합니다. 이 프로세스를 더 빨리 수행하려면 어떻게해야합니까? 다음은 현재 코드입니다.파이썬에서 어떻게 빨리 검색 할 수 있습니까?

filltaxlist = open("file with query number.txt", "rw") 
fulltaxa = open("output file with hit line match", "rw") 

for line in filltaxalist: 
    line = line.strip() 
    taxid = re.split("\t", line) 
    lookup = taxid[5] # this value is a number and I need the exact match only so I convert it to an integer 
    int1 = int(lookup) 
    for line in open("File to search.txt", "r"): 
     data = re.split(',', line) 
     hit = int(data[0]) # every value in this file is a number separated by a , 
     if lookup in line: 
      if int1 == hit: 
       fulltaxa.write(line) 

매우 느리게 작성되었으므로 잘 작동합니다. 또한 내가 검색하는 파일의 크기가 GB 이상입니다. filltaxlist 라인의

예 :

cvvel_1234 403454663 29.43 3e-30 55.55555555234 1172189 
cvell_1444 2342333  30.00 1e-50 34.34584359345 5911 
cvell_1444 234230055 23.23 1e-60 32.23445983454 46245 
cvell_1444 233493003 23.44 1e-43 35.23595604593 46245 

fulltaxa 반환해야합니까 :

1172189, 5943, 1002030, 12345 
5911, 11234, 112356, 234, 3456, 44568, 78356 
46245, 123, 3432456, 123488976, 23564, 334 
46245, 123, 3432456, 123488976, 23564, 334 
+0

'filltaxalist'의 모든 줄마다 파일을 한 번 읽습니다. – Blender

+0

'if int == hit'은'if int1 == hit'이어야합니다. –

+0

'filltaxlist'는 매우 큽니까? –

답변

4

사용을

다른 사람이 언급 한 것처럼

이, 가장 쉬운 방법은 아마도 덤핑 할 것입니다 데이터베이스를 이 db (예 : sqllite). 언어와 인터페이스해야하는 경우 Python 바인딩을 사용할 수 있습니다.

순수 파이썬 솔루션

당신은 (때문에 중첩의 순서에) 완전히 filltaxlist의 각 항목에 대해 fulltaxa 읽기, 다음 읽기, 먼저 쿼리를 캐시하는 것이 더 효율적입니다 fulltaxa 한 번만, 다음 종류 출력은 fulltaxa의 순서를 다시 얻습니다.

쿼리의 순서가 가져 오기 때문에 우리는 FIFO 구조를 사용해야합니다. 우리의 경우에는 deque이 좋을 것입니다.

from collections import defaultdict 
filltaxlist = open("file with query number.txt", "rw") 
fulltaxa = open("output file with hit line match", "rw") 

possibles = {} 
for i, line in enumerate(filltaxalist): 
    line = line.strip() 
    taxid = re.split("\t", line) 
    lookup = taxid[5] # this value is a number and I need the exact match only so I covert it to an integer 
    int1 = int(lookup) 
    possibles[int1] = i 

output_lines = defaultdict(list) 
for line in open("File to search.txt", "r"): 
    data = re.split(',', line) 
    hit = int(data[0]) # every value in this file is a number separated by a , 
    if hit in possibles: 
     output_lines[possibles[hit]].append(line) 

fulltaxa.writelines(line for lines in output_lines.values() for line in lines) 

당신은 쿼리에서 실행하면 위의 코드는 IndexError에게

일부 기타 사소한 개선을 발생합니다.

data = re.split(',', line) 

아마보다 느린

data = line.split(',') 

하지만 당신이 귀하의 경우 meaninfgul 있는지 확인하기 위해 프로필해야한다.

+0

고맙습니다. 집합은 고유 한 값만 수집합니까? 나는 이것을 원래 목록으로 읽었지만 filltaxalist에는 여전히 값을 중복하여 검색해야합니다. –

+0

세트는 고유 한 값만 수집하고 각 카운터의 인스턴스 수를 알아야 할 경우 [카운터] (http://docs.python.org/2/library/collections.html#collections.Counter)에 대해 전환하십시오. 값 (예 : 쿼리 목록에 3 개의 중복 항목이있는 경우 첫 번째 3 개의 instanals를 검색하려는 경우). – cmh

+0

이 프로세스가 제대로 작동하려면 날씨 순서가 중복되거나 고유 한 값이 매우 중요하므로 줄 단위로 이동해야합니다. filltaxlist의 1 행은 fulltaxa의 1 행과 일치해야합니다. 나는 명확성을 위해 각 파일의 예제를 질문에 추가 할 것이다. –

1

귀하의 알고리즘은 O (m * n)입니다. 사전을 사용하여 대신 O (m + n) 알고리즘을 만들 수 있습니다. m이 작더라도 파이썬에서 상당한 개선이 될 것입니다. 파이썬에서는 사전 액세스의 일정한 요소가 다른 구문과 크게 다르지 않습니다.

filltaxalist = open("file with query number.txt", "rw") 
fulltaxa = open("output file with hit line match", "rw") 

filltaxadict = {} 
for i, line in enumerate(filltaxalist): 
    line = line.strip() 
    taxid = re.split("\t", line) 
    lookup = taxid[5] # this value is a number and I need the exact match only so I convert it to an integer 
    int1 = int(lookup) 

    filltaxadict[int1] = i 

results = [[]] * len(filltaxadict) 
for line in open("File to search.txt", "r"): 
    data = re.split(',', line) 
    hit = int(data[0]) # every value in this file is a number separated by a , 
    match = filltaxadict.get(hit) 
    if match is not None: 
     results[match].append(line) 

for result in results: 
    fulltaxa.writelines(result) 

이렇게하면 중복 된 순서로 처리됩니다. 필요가 없으면 약간 더 간단합니다. 검색 할 파일이 클 수 있습니다. 이것은 그 내용을 메모리에 보관하지 않을 것이며, 필자 주의자의 내용 중 일부만이 비정상적으로 크지 않다고 가정합니다.

관련 문제