2016-05-25 4 views
0

У меня есть адресная книга и вы хотите напечатать все (возможно несколько) записей, для данной «фамилии» эффективно.условно чтение блока строк из файла в python

Запись имеет следующую структуру:

Johnsen 
Paul 
First Street 
313 
94134 
State1 
1343154622525 
[email protected] 

Parker 
Peter 
Scnd Street 
44 
91347 
State2 
1343154622525 
[email protected] 

... 

Мой код пока выглядит следующим образом:

print("1) Look up by last name") 
print("2) Add a person to address book") 
print("3) Quit App") 

choice = int(input("Enter your choice (1/2/3): ")) 
if choice == 1: 
    lname = input("Enter last name: ") 

    addressbook = open("addressbook.txt", "r") 

    import itertools 
    lnameLines = itertools.islice(addressbook, 0, None, 9) 
    matchingLines = [] 
    lineNumber = 0 
    for n in lnameLines: 
     if lname.lower() == n.rstrip().lower(): 
      matchingLines.append(lineNumber) 
    lineNumber = lineNumber + 9 
print(matchingLines) 

Что это урожайность, является стартовой линией сопоставления 9-линии-блока к читать (включая пробел). Теперь мне интересно, как сгенерировать и использовать последовательность, которая снова откроет файл и будет читать только соответствующие блоки для поиска. Я уверен, что есть более эффективный подход к этому, мне интересно.

Спасибо за помощь.

+0

строки не очень полезны ... для правильного выполнения вам нужны фактические смещения байтов в файле ... но, возможно, посмотрите на модуль 'shelve', который является довольно простым (хотя и не идеальным) способом сделать что-то подобное, с некоторыми предварительными работами ... –

ответ

0

Вы всегда можете загрузить файл в файл dict, где ключ является l_name, а данные - все. Я написал для вас небольшую рабочую часть. Я бы рекомендовал создать класс Address_book, который имеет функции для загрузки данных, поиска, добавления данных и записи данных. Это было бы просто и прямо, но я не собираюсь делать все для вас!

def load_book(book): 
    #assuming your layout never changes 

    f = open(book, 'rb').readlines() 
    ind = 0 

    for i in f: 
     if i == '\r\n': #find the empty line seperating each person 
      f[ind] = '--' 
     ind += 1 

    f = [x.split(':') for x in ''.join(f).replace('\r', '').replace('\n', '').replace(' ', ':').lower().split('--')] 

    data = {} 
    for i in f: 
     data[i[0]] = list(x for x in i if i != '') 

    return data 

def search_book(book, person): 
    try: 
     return book[person.lower()] 
    except: 
     for i in book: 
      if person.lower() in i: 
       return book[i] 
     else: 
      raise KeyError 

book = load_book('add') 
print search_book(book, 'Parker') 
0

Если ваш файл достаточно мал, чтобы поместиться в памяти, вы можете хранить данные в Словаре, где каждая фамилия соответствует списку одной или более записи:

from collections import defaultdict 

with open('test.txt') as f: 
    dct = defaultdict(list) 
    for block in f.read().split('\n\n'): 
     dct[block[:block.find('\n')].strip()].append(block) 


def lookup(last_name): 
    print('\n\n'.join(dct.get(last_name, []))) 


# In [61]: q.lookup('Johnsen') 
# Johnsen 
# Paul 
# First Street 
# 313 
# 94134 
# State1 
# 1343154622525 
# [email protected] 

тест. txt

Johnsen 
Paul 
First Street 
313 
94134 
State1 
1343154622525 
[email protected] 

Parker 
Peter 
Scnd Street 
44 
91347 
State2 
1343154622525 
[email protected] 
0

Спасибо за ваши альтернативные предложения. Я действительно ценю идею создания класса адресной книги, а также подхода в памяти, хотя и не совсем того, что мне нужно.

Мой - не самый эффективный, но простой - обходной путь выглядит следующим образом:

choice = int(input("Enter your choice (1/2/3): ")) 
if choice == 1: 
lname = input("Enter last name: ") 

book = open("addressbook.txt", "r") 

for i, line in enumerate(book): 
    if (i % 9 == 0 and 
     lname.lower() == line.rstrip().lower()): 
     load = 9 
    if load > 0: 
     print(line.rstrip()) 
     load = load - 1 

Любых suggetions по избежанию перебора каждой строки текстового файла высоко ценятся.