【问题标题】:Using Python's csv.dictreader to search for specific key to then print its value使用 Python 的 csv.dictreader 搜索特定键,然后打印其值
【发布时间】:2013-05-14 12:50:59
【问题描述】:

背景:

我在尝试搜索某些 CSV 文件时遇到问题。 我浏览了 python 文档:http://docs.python.org/2/library/csv.html 关于 csv 模块的csv.DictReader(csvfile, fieldnames=None, restkey=None, restval=None, dialect='excel', *args, **kwds) 对象。

我的理解是csv.DictReader 假定文件的第一行/第一行是字段名,但是,我的 csv 字典文件只是以“key”、“value”开头并持续至少 500,000 行。

我的程序将询问用户他们正在寻找的标题(因此是键),并使用打印功能将值(即第二列)显示到屏幕上。我的问题是如何使用 csv.dictreader 搜索特定键,并打印其值。

样本数据: 以下是 csv 文件及其内容的示例...

"Mamer","285713:13"

"Champhol","461034:2"

"Station Palais","972811:0"

所以如果我想找到“Station Palais”(输入),我的输出将是 972811:0。我能够操作字符串并创建整个程序,我只需要 csv.dictreader 的帮助。感谢任何帮助。

编辑部分:

    import csv

    def main():
        with open('anchor_summary2.csv', 'rb') as file_data:
        list_of_stuff = []
        reader = csv.DictReader(file_data, ("title", "value"))
            for i in reader:
              list_of_stuff.append(i)
            print list_of_stuff

    main()

【问题讨论】:

  • 我认为您正在错误地考虑 DictReader。 DictReader 将第一行的每一列中的值作为键,并且在它读取的每一行上,可以通过键名而不是列号来访问列。是在寻找访问单个值的最佳方式,还是要访问许多随机放置的值?
  • 我的程序需要遍历 csv 文件,查找我为该特定迭代提供的密钥,并打印出它的值。整个文件将始终只是 2 列(键、值)。你是这个意思吗?如果有比 DictReader 更好的选择,那也欢迎。

标签: csv python-2.7 dictionary


【解决方案1】:

目前接受的答案很好,但有一种更直接的方式来获取数据。 Python 中的dict() 构造函数可以采用任何可迭代对象。

此外,您的代码在 Python 3 上可能存在问题,因为 Python 3 的 csv 模块要求文件以文本模式打开,而不是二进制模式。您可以使用 io.open 而不是 open 使您的代码与 2 和 3 兼容。

import csv
import io

with io.open('anchor_summary2.csv', 'r', newline='', encoding='utf-8') as f:
    data = dict(csv.reader(f))

print(data['Champhol'])

作为警告,如果您的 csv 文件在第一列中有两行具有相同的值,则后面的值将覆盖前面的值。 (其他发布的解决方案也是如此。)

如果你的程序真的只应该打印结果,那么真的没有理由构建一个键控字典。

import csv
import io


# Python 2/3 compat
try:
    input = raw_input
except NameError:
    pass


def main():
    # Case-insensitive & leading/trailing whitespace insensitive
    user_city = input('Enter a city: ').strip().lower()

    with io.open('anchor_summary2.csv', 'r', newline='', encoding='utf-8') as f:
        for city, value in csv.reader(f):
            if user_city == city.lower():
                print(value)
                break
        else:
            print("City not found.")

if __name __ == '__main__':
    main()

这种技术的优点是 csv 不会加载到内存中,并且数据只会迭代一次。我还在两个键上添加了一些调用lower 的代码,以使匹配不区分大小写。另一个优点是,如果用户请求的城市位于文件顶部附近,它几乎会立即返回并停止查看文件。

话虽如此,如果搜索性能是您的首要考虑因素,您应该考虑将数据存储在数据库中。

【讨论】:

    【解决方案2】:

    您链接到的文档提供了一半的答案:

    class csv.DictReader(csvfile, fieldnames=None, restkey=None, restval=None, dialect='excel', *args, **kwds)

    [...] 将读取的信息映射到一个字典,其键由可选的 fieldnames 参数给出。如果省略 fieldnames 参数,则 csvfile 第一行的值将用作字段名。

    似乎如果传递了fieldnames 参数,则给定文件的第一条记录将不会被解释为标题(将使用该参数)。

    # file_data is the text of the file, not the filename
    reader = csv.DictReader(file_data, ("title", "value"))
    for i in reader:
      list_of_stuff.append(i)
    

    这将(显然;我一直遇到问题)产生以下数据结构:

    [{"title": "Mamer", "value": "285713:13"},
     {"title": "Champhol", "value": "461034:2"},
     {"title": "Station Palais", "value": "972811:0"}]
    

    可能需要通过以下方式进一步将其处理为标题到值的映射:

    data = {}
    for i in list_of_stuff:
      data[i["title"]] = i["value"]
    

    现在只需使用data 的键和值来完成您的任务。


    这里是字典理解:

    data = {row["title"]: row["value"] for row in csv.DictReader(file_data, ("title", "value"))}
    

    【讨论】:

    • import csv def main(): file_data = 'anchor_summary.csv' list_of_stuff = [] reader = csv.DictReader(file_data, ("title", "value")) for i in reader: list_of_stuff .append(i) print list_of_stuff main() .................................也是这个论坛的新手,正在尝试用代码整齐地响应对我来说似乎是一个挑战,抱歉…………无论如何我尝试了上面的代码来帮助我理解你答案的第一部分,没有运气:(
    • @RHK-S8 注意:file_data 是文件的内容,而不是文件名。 (另外,您可以编辑您的问题。)
    • 哎呀,我注意到 500,000 行需要一段时间,所以我制作了一个较短的 .csv 文件用于测试目的。现在它起作用了!您能否详细说明答案的最后一部分(第三格雷码部分)的意思,您在其中介绍了 data={} 等?
    • @RHK-S8 这会将数据从dicts 列表(每个都有名称和值)转换为将名称映射到值的单个dict
    • 啊好的,我已经实现了,我明白你的意思。所以现在我可以用所需的键迭代“数据”,以检索它的值吗?我该怎么做呢? (我想我认为 csv 文件是一个现成的字典,我可以简单地搜索密钥并获得它的值(我的错误)............因为在一天结束时, csv 文件需要将值(那些值/数字 r wikipages,将它们链接到页面标题)提供给变量,因此我最终可以在下一步中将它们用于动态 SPARQL 查询
    猜你喜欢
    • 2018-07-11
    • 2017-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多