2013-05-29 18 views
6

Mam duży plik (A.txt) z 2 GB zawierający listę ciągów znaków ['Question','Q1','Q2','Q3','Ans1','Format','links',...].Sprawdź, czy ciąg znaków znajduje się na liście ciągów o wielkości 2 GB w pythonie

Teraz mam inny większy plik (1TB) zawierający powyższe ciągi w 2. pozycji:

wyjściowa:

a, Question, b 
The, quiz, is 
This, Q1, Answer 
Here, Ans1, is 
King1, links, King2 
programming,language,drupal, 
..... 

chcę zachować linie, których druga pozycja zawiera ciągi w wykazie przechowywane w pliku A.txt. Oznacza to, że chcę zachować (sklep w innym pliku) Poniższa wspomniane linie:

a, Question, b 
This, Q1, Answer 
Here, Ans1, is 
King1, links, King2 

wiem, jak to zrobić, gdy długość listy w pliku (A.txt) jest 100..using ' każdy'. Ale nie rozumiem, jak powinienem się do tego zabrać, gdy długość listy w pliku (A.txt) wynosi 2 GB.

Odpowiedz

8

Nie używaj listy; zamiast tego użyj zestawu.

Czytaj pierwszy plik do zestawu:

with open('A.txt') as file_a: 
    words = {line.strip() for line in file_a} 

0,5 GB słów jest nie że dużo do przechowywania w zestawie.

Teraz można przetestować przed words w O (1) stałą czasową:

if second_word in words: 
    # .... 

Otwórz plik i proces druga linia jest linią, być może za pomocą modułu csv Jeśli linie słowa są oddzielone przecinkami.

Aby uzyskać większy zestaw słów, należy zamiast tego użyć bazy danych; Python pochodzi z sqlite3 Biblioteka:

import sqlite3 

conn = sqlite3.connect(':memory:') 
conn.execute('CREATE TABLE words (word UNIQUE)') 

with open('A.txt') as file_a, conn: 
    cursor = conn.cursor() 
    for line in file_a: 
     cursor.execute('INSERT OR IGNORE INTO words VALUES (?)', (line.strip(),)) 

następnie testu przeciwko że:

cursor = conn.cursor() 
for line in second_file: 
    second_word = hand_waving 
    cursor.execute('SELECT 1 from words where word=?', (second_word,)) 
    if cursor.fetchone(): 
     # .... 

Chociaż używam bazy :memory: tutaj, SQLite jest wystarczająco inteligentny, aby zapisać dane w plikach tymczasowych po uruchomieniu napełniania pamięć. Połączenie :memory: jest w zasadzie tylko tymczasową, jednorazową bazą danych. Możesz także użyć prawdziwej ścieżki do pliku, jeśli chcesz ponownie użyć bazy słów.

+1

Wygląda na to, że 0,5 gb właśnie przeskoczyło do 2 GB w edycji ... –

+0

@JonClements: Opcja cofania, sqlite. –

+0

Niezbyt konieczne, ale zapytanie może zostać przepisane jako IN/ANY lub EXISTS - lub jeśli ktoś ma serwer redis lub podobny, który będzie działał ładnie ... –

1

Rozpocznij od odpowiedzi: Martijn Pieters. Jeśli to zbyt wolno, możesz użyć numeru Bloom Filter, aby zmniejszyć liczbę przypadków korzystania z bazy danych, eliminując linie, które nie mogą pasować do żadnych słów na liście. Python jest dostarczany z wbudowanym hash function, którego można użyć do jednego z skrótów do tabeli filtrów, i można wyszukać dowolną liczbę innych.

+0

+1 Dzięki za pomoc –

Powiązane problemy