2011-08-09 5 views
2

~ 2,000 만 줄 (~ 1.5GB)이 포함 된 파일이 있습니다. 각 행의 형식이다Python - 큰 파일을 필터링/정렬하기위한 제안 사항?

entry_1 entry_2 entry_3 ......... entry_5 

파일하지만 형태의 중복 포함 된 행의

entry_2 entry_1 entry_3 ......... entry_5 

내용은 동일하지만, 처음 두 요소 (아마도 항상) 종종 스위치.

누구나이 크기의 파일에서 이러한 특성의 중복을 제거하는 방법에 대한 제안이 있습니까?

감사합니다.

+0

당신이 파이썬을 사용해야하는 이유를 몇 가지 이유가? 셸에서 매우 쉽고 효율적입니다. 머리, 꼬리 및 정렬 만 사용하십시오. –

+0

줄의 순서가 중요합니까? –

+0

그래서 entry_1과 antry_2가 바뀌 었는지 어떻게 알 수 있습니까? 이 두 가지가 올바르게 주문 된 후에 모든 복제물을 삭제해야한다는 생각입니까? 만약 그렇다면, 나는 1 패스를 사용하여 python에서 패스를 사용하여 entry1/2를 수정 한 다음 명령 행에서'sort -u'를 사용하도록 제안 할 것입니다. –

답변

4

적합한 솔루션은 가지고있는 제약 조건과이 작업을 얼마나 자주 실행해야하는지에 따라 다릅니다.

visited = set() # use set for faster lookups 
with open(out_filename, "w") as outfile: 
    with open(in_filename, "r") as infile: 
     for line in infile: 
      x = line.split() 
      k = (tuple(sorted(x[:2])), tuple(x[2:])) 
      if k not in visited: 
       outfile.write(line) 
       visited.add(k) 

메모리 사용량이 독특한 의 수에 따라 달라집니다이 한 번 (또는 가끔) 운영 및 메모리 사용량이 큰 문제가되지 않는 경우,이 같은 충분한 것 인 경우

우리가 추적해야 할 항목은 visited입니다. 중복이 많지 않으면 메모리의 거의 모든 데이터로 끝납니다. 메모리 사용량이 문제된다

경우 여러 단계에서이 작업을 수행 할 수 있습니다

  1. 먼저 전처리에게 파일을 각 행의 첫 번째 두 요소를 정렬하여.
  2. 줄 단위로 전체 파일 정렬
  3. 중복 된 항목이 함께 표시되므로 중복 된 항목을 제거하는 것이 이제는 간단합니다.

3 정렬을 수행하는 동안 항목을 비교할 때 중복을 간단히 삭제할 수 있으므로 병합 할 수 있습니다.

셸 사용에 신경 쓰지 않으면 2 단계와 3 단계는 sort -u yourfile을 사용하여 수행 할 수 있습니다.

파일의 줄 순서가 변경된다는 점에 유의하십시오 (위에서 언급 한 내용은 문제가되지 않음).

이 크게 당신이 저장하고 (set() 대신에) 방문 항목을 찾기 위해 파일 기반 DB를 사용할 수 있습니다, 성능이 약간 저하되는 대신 메모리 사용을 줄일 수 있습니다.

메모리의 항목 해시를 저장하여 해쉬가 일치 할 때만 쿼리하여 해당 항목이 실제로 동일한 지 확인합니다. 해시는 각 항목의 첫 번째 문자를 취하거나 내장 된 hash() 함수를 사용하거나, existing hash algorithm을 선택하는 것처럼 간단 할 수 있습니다. 각 방법은 성능, 해시 크기 및 충돌 빈도 간의 절충안입니다. 좋은 선택은 데이터와 제약 조건에 달려 있습니다.

최적의 솔루션을 찾으려면 약간의 노력이 필요합니다. 이 작업을 자주 수행해야하는 경우에만 시작할 가치가 있습니다.

1
separator = " " 
aSet = set() 
with open('myfile', 'rU') as infile: 
    for line in infile: 
     tempLine = line.split(separator) 
     tempLine = tempLine[1:2] + tempLine[0:1] + tempLine[2:] 
     tempLine = separator.join(tempLine) 
     if line not in aSet and tempLine not in aSet: 
      aSet.add(line) 

지금, aSet에 관계없이 entry_1entry_2가 교체되었는지 여부의 고유 라인의 목록이 포함되어 있습니다.

편집 : 모든 항목을 교환하고 라인이 여전히 다음, 독특한 간주 될 수있는 경우 :

separator = " " 
aSet = set() 
with open('myfile', 'rU') as infile: 
    for line in infile: 
     aSet.add(frozenset(line.split(separator))) 
관련 문제