2013-02-13 4 views
4

필자는 두 개의 텍스트 파일에 일치하는 줄이 많이 있어야하며 정확히 얼마나 많은 줄이 파일간에 일치하는지 알아야합니다. 문제는 두 파일 모두 상당히 큽니다 (한 파일은 약 3GB이고 다른 파일은 16GB 이상). 따라서 read() 또는 readlines()를 사용하여 시스템 메모리로 읽는 것은 매우 문제가 될 수 있습니다. 어떤 팁? 필자가 작성한 코드는 기본적으로 단지 2 개의 루프와 if 문을 비교하는 코드입니다.파이썬에서 두 파일을 효율적으로 반복하는 방법은 무엇입니까?

+1

파일들이 정렬되어 있습니까? 그렇지 않다면 미리 정렬 할 수 있습니까? – Johnsyweb

+0

@ TheFoxx 일치 할 줄이 더 많거나 적은 줄이 중간에 있거나 순서가 뒤섞인 동일한 순차 순서로 나타납니다. –

+0

열린 파일 객체는 반복자이므로 다음 줄을 얻기 위해'next()'를 호출 할 수 있습니다. 추가 라인 버퍼를 사용하면 두 라인을 반복하고 일치하는 라인을 쉽게 찾을 수 있습니다. –

답변

0

입력 해 주셔서 감사합니다. 그러나 내가 끝내었던 것은 고통스럽게 단순했다. 이런 일을 시도하고 있었는데 전체 파일을 읽었습니다. 내가하고 결국 무엇

file = open(xxx,"r") 
for line in file: 
     if..... 

은 두 번째 라인하여 파일 라인을 취

for line in open(xxx) 
    if..... 

했다.매우 시간이 많이 걸리지 만, 나는 약간의 시간이 걸리는 마법 같은 방법이 없다는 것을 거의 받아 들였습니다 : (

2

입력 파일이 매우 크기 때문에 성능을 신경 쓰는 경우 grep -f을 사용하는 것이 좋습니다. -f 옵션은 파일에서 패턴을 읽으므로 정확한 의미에 따라 필요한 작업을 수행 할 수 있습니다. 전체 라인 일치 만 취하기 위해서는 -x 옵션도 필요합니다. 그래서 파이썬의 모든 것은 다음과 같이 보일 수 있습니다 :

child = subprocess.Popen(['grep', '-xf', file1, file2], stdout=subprocess.PIPE) 
for line in child.stdout: 
    print line 
+0

이것은 매우 흥미 롭습니다, 당신은 자식 변수가 무엇을하고 있는지 설명 할 수 있습니까? subprocess.Popen 비트처럼 ?? – TheFoxx

+0

유닉스에서 파일을 그냥 grepping하고 메모리 문제가 다시 발생하여 프로세스가 중단되기 전에 프로세스를 종료해야했습니다. – TheFoxx

1

유닉스를 사용하지 않는 이유 grep? 솔루션 플랫폼을 독립적으로 원할 경우이 솔루션은 작동하지 않습니다. 그러나 유닉스에서는 작동한다. 파이썬 스크립트에서이 명령을 실행하십시오.

grep --fixed-strings --file=file_B file_A > result_file 

또한이 문제는 map-reduce로가는 좋은 이유 인 것처럼 보입니다.

업데이트 0 : 설명해주십시오. file_B에서 --fixed-strings = Interpret PATTERN as a list of fixed strings, separated by newlines, any of which is to be matched.

--file= Obtain patterns from FILE, one per line. 그래서 우리가하고 싶었어 것은 점점 패턴은 패턴의 순서로 file_Afixed-strings 치료의 내용에 대해 그들이 파일에있는 방법을 일치. 희망이 그것을 명확하게. 당신은이 작업을 수행 할 수 있습니다 :

grep --fixed-strings --file=file_B file_A | wc -l 

UPDATE 1 - 당신이 선을 위 grep의 약간의 수정을 일치의 수를 원하기 때문에

우리는 수를 얻을. 먼저 각 파일을 한 줄씩 따로 처리하십시오. 메모리로 전체 파일을 읽지 마라. 한 줄을 읽을 때이 줄의 md5 해시를 계산하여 다른 파일에 씁니다. 이 두 파일을 모두 수행하면 md5 해시로 채워진 두 개의 새 파일이 생성됩니다. 나는 md5가 i/p 문자열과 관계없이 16 바이트이기 때문에이 두 파일의 크기가 원본 파일보다 훨씬 작기를 바라고 있습니다. 이제 메모리 문제가 거의 없거나 전혀없는 grep 또는 다른 diffing 기법을 사용할 수 있습니다. - Srikar 1 분 전 편집

업데이트 2 : (며칠 후) 이것을 할 수 있습니까? mysql에 2 개의 테이블 table1, table2을 생성하십시오. 두 필드 모두 id, data 만 있습니다. 이 두 테이블에 두 파일을 한 줄씩 입력하십시오. 그런 다음 쿼리를 실행하여 중복 횟수를 찾습니다. 두 파일을 모두 살펴 봐야합니다. 그게 다예요. 우리는 그 사실에서 벗어날 수 없습니다. 이제 dups 발견 방법을 최적화 할 수 있습니다. MySQL은 이러한 옵션 중 하나입니다. RAM 공간, 색인 생성 등을 수행하는 데 필요한 많은 사항을 제거합니다.

+0

나는 실제로 유닉스 grep 사용을 고려해 봤지만 파이썬에서는 상당히 편안하다. (하지만 유닉스에 대해 더 많이 배워야한다!) 나는 당신의 코드를 이해하지 못한다. 물론 file_B와 file_A는 내 파일이지만, 고정 된 문자열 비트를 얻지 못하겠습니까? – TheFoxx

+0

좋습니다. 간단합니다. 2 파일의 내용 대부분이 같다고 했으니 까. 이 단일 명령어는 이것을 당신을 위해 발견합니다. 위의 업데이트를 참조하십시오. –

+0

감사합니다. 문제는 다시 한번 메모리입니다.이 grep을 실행하면 컴퓨터가 거의 추락했습니다. 실제로 내 컴퓨터를 추락시키기 전에 그것을 죽여야했습니다. – TheFoxx

관련 문제