【问题标题】:The best way to search a file and return required fields from rows搜索文件并从行中返回必填字段的最佳方式
【发布时间】:2017-12-26 10:47:56
【问题描述】:

我有以下完美运行的代码。它在 txt 文件中搜索 ID 号,如果存在,则返回名字和姓氏。

完整列表:https://repl.it/Jau3/0

import csv

#==========Search by ID number. Return Just the Name Fields for the Student
with open("studentinfo.txt","r") as f:
  studentfileReader=csv.reader(f)
  id=input("Enter Id:")
  for row in studentfileReader:
    for field in row:
      if field==id:
        currentindex=row.index(id)
        print(row[currentindex+1]+" "+row[currentindex+2])

文件内容

001,Joe,Bloggs,Test1:99,Test2:100,Test3:33
002,Ash,Smith,Test1:22,Test2:63,Test3:99

出于教学和学习的目的,我想知道是否有其他方法可以实现相同的目标(优雅、简单、pythonic),或者这确实是最好的解决方案?

我的问题源于这样一个事实,即似乎可能存在一种内置方法或某些函数可以更有效地检索当前索引并搜索字段......也许不是。

提前感谢您的讨论和任何解释,我将接受作为答案。

【问题讨论】:

  • 这不是一个很好的解决方案。对于初学者,当您的 ID 始终存储在第一列时,您循环遍历行中的所有字段,如果找不到 ID,您没有任何消息提醒用户,并且您将自己限制为单个一致的 ID 查找当你遍历打开的文件时。

标签: python file csv search


【解决方案1】:

就查找时间而言,您可以将其读入列表甚至更好的字典,然后只需使用以下内容:

if in lif in d(l 或 d 分别是列表/字典)

然而,一个有趣的讨论,关于这是否是最简单的方法,或者你现有的解决方案是否是。

字典:

   1 # retrieve the value for a particular key
   2 value = d[key]

关于使用字典的时间复杂度和效率的说明:

Python 映射必须能够在给定特定键对象的情况下确定哪个(如果有)值对象与给定键关联。一种简单的方法是存储(键,值)对的列表,然后在每次请求值时按顺序搜索列表。立即您可以看到,如果有大量项目,这将非常慢 - 就复杂性而言,该算法将是 O(n),其中 n 指的是映射中的项目数。

Python 的字典 是这里的答案,尽管它并不总是最好的解决方案 - 该实现通过要求关键对象提供“哈希”将字典查找的平均复杂度降低到 O(1) “ 功能。在您的情况下,由于您正在处理的数据在结构上并不是非常复杂,因此坚持现有的解决方案可能是最容易的,尽管如果您追求的是时间效率,当然应该考虑使用字典。

【讨论】:

  • 建立一个字典可能是一件有趣的事,有几个原因,然后根据 0(n) 等进行搜索...
【解决方案2】:

如果列表保持这种格式,您可以通过索引访问该行的字段以将其压缩一点。

for row in studentfileReader:
    if row[0]==id:
        print(row[1]+" "+row[2])

如果 ID 不在开头但介于两者之间,它也会避免匹配,例如"测试1:002"

【讨论】:

  • 有趣。谢谢。是否有其他用户可以投票选出最佳方法的功能。我怎么可能知道什么才是真正的 Pythonic 和最好的?!您的解决方案会为相应的 iD 打印吗?我假设是这样,尚未测试。
  • 老实说,我无法回答你什么是最 Pythonic,只是在这种情况下,直接访问似乎更有用也更安全。
【解决方案3】:

我真的不知道是否有诸如“pythonic”之类的方法来查找匹配键上的记录,但这里有一个示例,它在您自己的示例和其他答案上添加了一些有趣的东西,例如生成器的使用和理解。此外,还有什么比单线更符合 Python 的呢。

any 是 python 内置的,你可能会感兴趣知道它的存在,因为它完全按照你的方式工作。

with open("studentinfo.txt","r") as f:
    sid=input("Enter Id:")
    print any((line.split(",")[0] == sid for line in f.readlines()))

【讨论】:

  • 我喜欢这个 - 但出于教学/学习目的,很难轻松解释它(在分析每一行并解释它方面并不明显)。谢谢!
  • 我同意,这不是应该对初学者直言不讳的事情。但是既然你提到了教学目的,我认为引入一些 python 关键概念很有趣:)。
【解决方案4】:

您可能应该考虑使用csv.DictReader 进行此用途,因为您的表格数据具有一致的列。

如果您只想检索一次数据,那么您可以简单地遍历文件,直到第一次出现所需的 id,如下所示;

import csv

def search_by_student_id(id):
    with open('studentinfo.txt','r') as f:
        reader = csv.DictReader(f, ['id', 'surname', 'first_name'],
                                restkey='results')
        for line in reader:
            if line['id'] == id:
                return line['surname'], line['first_name']

print(search_by_student_id('001'))
# ('Joe', 'Bloggs')

但是,如果您计划多次从该数据中查找条目,则需要创建一个字典,该字典的创建成本更高,但可以显着减少查找时间。然后你可以像这样查找数据;

def build_student_id_dict():
    with open('studentinfo.txt','r') as f:
        reader = csv.DictReader(f, ['id', 'surname', 'first_name'],
                                restkey='results')
        student_id_dict = {}
        for line in reader:
            student_id_dict[line['id']] = line['surname'], line['first_name']
        return student_id_dict

student_by_id_dict = build_student_id_dict()
print(student_by_id_dict['002'])
# ('Ash', 'Smith')

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    • 2010-11-17
    • 2018-11-10
    • 2010-10-12
    • 2010-11-16
    • 1970-01-01
    相关资源
    最近更新 更多