【问题标题】:conditionally reading a block of lines from file in python有条件地从python中的文件中读取一行
【发布时间】:2016-05-25 14:35:37
【问题描述】:

我有一个地址簿,想打印所有(可能是多个)条目, 有效地为给定的“姓氏”。

条目具有以下结构:

Johnsen  
Paul  
First Street  
313  
94134  
State1  
1343154622525  
myemail101@mail.com  

Parker  
Peter  
Scnd Street  
44  
91347  
State2  
1343154622525  
myemail224@mail.com  

...

到目前为止,我的代码如下所示:

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 行块的起始行(包括空白行)。 现在我想知道如何生成和使用将再次打开文件并仅读取匹配块以进行查找的序列。 我很确定还有一种我很好奇的更有效的方法。

感谢您的帮助。

【问题讨论】:

  • 行不是很有用...要正确执行此操作,您需要文件中的实际字节偏移量...但也许可以查看shelve 模块,这很容易(尽管不完美)做类似事情的方法,有一些准备工作......

标签: python io conditional readline


【解决方案1】:

您总是可以将文件加载到一个字典中,其中键是 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')

【讨论】:

    【解决方案2】:

    如果您的文件足够小以适合内存,您可以将数据存储在一个字典中,其中每个姓氏对应一个或多个条目的列表:

    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  
    # myemail101@mail.com  
    

    test.txt

    Johnsen  
    Paul  
    First Street  
    313  
    94134  
    State1  
    1343154622525  
    myemail101@mail.com  
    
    Parker  
    Peter  
    Scnd Street  
    44  
    91347  
    State2  
    1343154622525  
    myemail224@mail.com
    

    【讨论】:

      【解决方案3】:

      感谢您的替代建议。我真的很欣赏构建地址簿类的想法以及内存中的方法,尽管这不是我所需要的。

      我的 - 不是最有效但最简单的 - 解决方法如下所示:

      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
      

      非常感谢任何有关避免遍历文本文件每一行的建议。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-04-28
        • 2022-08-12
        • 2020-08-18
        • 1970-01-01
        • 1970-01-01
        • 2017-06-15
        • 2016-09-05
        • 1970-01-01
        相关资源
        最近更新 更多