【问题标题】:Search a single column for a particular value in a CSV file and return an entire row在 CSV 文件中搜索单个列以查找特定值并返回整行
【发布时间】:2012-04-29 21:06:17
【问题描述】:

问题

代码没有正确识别输入(项目)。即使 CSV 文件中存在这样的值,它也会简单地转储到我的失败消息中。谁能帮我确定我做错了什么?

背景

我正在开发一个小程序,该程序要求用户输入(此处未给出函数),搜索 CSV 文件(项目)中的特定列并返回整行。 CSV 数据格式如下所示。我已经从实际数量(49 个字段名称,18000+ 行)中缩短了数据。

代码

import csv
from collections import namedtuple
from contextlib import closing

def search():
    item = 1000001
    raw_data = 'active_sanitized.csv'
    failure = 'No matching item could be found with that item code. Please try again.'
    check = False

    with closing(open(raw_data, newline='')) as open_data:
        read_data = csv.DictReader(open_data, delimiter=';')
        item_data = namedtuple('item_data', read_data.fieldnames)
        while check == False:
            for row in map(item_data._make, read_data):
                if row.Item == item:
                    return row
                else:
                    return failure     

CSV 结构

active_sanitized.csv
Item;Name;Cost;Qty;Price;Description
1000001;Name here:1;1001;1;11;Item description here:1
1000002;Name here:2;1002;2;22;Item description here:2
1000003;Name here:3;1003;3;33;Item description here:3
1000004;Name here:4;1004;4;44;Item description here:4
1000005;Name here:5;1005;5;55;Item description here:5
1000006;Name here:6;1006;6;66;Item description here:6
1000007;Name here:7;1007;7;77;Item description here:7
1000008;Name here:8;1008;8;88;Item description here:8
1000009;Name here:9;1009;9;99;Item description here:9

备注

我在 Python 方面的经验相对较少,但我认为这将是一个很好的问题,以便了解更多信息。

我确定了打开 CSV 文件(并在关闭函数中包装)的方法,通过 DictReader 读取数据(以获取字段名称),然后创建一个命名元组以便能够快速选择所需的列输出(项目、成本、价格、名称)。列顺序很重要,因此使用 DictReader 和 namedtuple。

虽然有可能对每个字段名称进行硬编码,但我觉得如果程序可以在打开文件时读取它们,那么在处理具有相同列名称但不同的类似文件时会更有帮助列组织。

研究

【问题讨论】:

  • 你不需要在文件上使用closing() - 它的上下文管理器默认已经关闭了文件。只需使用with open(...) as file:
  • while check == False: 是什么?永远都是真的……
  • 好的。我基于 docs.python.org/py3k/library/… 使用了 close()。我在 open() 的文档中读到它确实关闭了 IO,但我只是觉得它比抱歉更安全,因为我不确定有什么区别。
  • 约翰,那是另一个声明的剩余部分。我试图彻底检查代码,但我错过了。过了一会儿,线条开始融合。
  • 是的,closing() 用于向尚不支持的对象添加对上下文管理器的支持。正如open() 返回的文件对象所做的那样,您可以放心地不使用它(尽管它基本上会产生最终结果)。

标签: python search csv


【解决方案1】:

你有这三个问题:

  • 您在第一次失败时返回,所以它永远不会超过第一行。
  • 您正在从文件中读取字符串,并与 int 进行比较。
  • _make 迭代字典键,而不是值,产生错误的结果 (item_data(Item='Name', Name='Price', Cost='Qty', Qty='Item', Price='Cost', Description='Description'))。

    for row in (item_data(**data) for data in read_data):
        if row.Item == str(item):
            return row
    return failure
    

这解决了手头的问题 - 我们检查一个字符串,并且仅在没有匹配的项目时才返回(尽管您可能希望开始将字符串转换为数据中的整数,而不是对字符串/整数问题)。

我还改变了你循环的方式——使用生成器表达式使语法更自然,对来自 dict 的命名属性使用正常的构造语法。这比使用_makemap() 更简洁、更易读。它还修复了问题 3。

【讨论】:

  • 啊,好吧。谢谢!我现在看到我的错误在哪里。如果您能够将 map() 函数编写为更自然的语法,是否存在特定的原因?我使用 map() 的原因是有许多其他示例一直在使用它。
  • 有时使用map() 更易读——例如map(int, list_of_strings) 使列表中的每个项目都成为int,有些人更喜欢[int(x) for x in list_of_strings],因为你不需要发明变量。通常 list、set 和 dict 组合或生成器表达式是更好的解决方案。 map() 对于习惯于函数式语言的人来说也是一个熟悉的概念。这也是语言中存在理解之前的遗留问题。
猜你喜欢
  • 2014-11-22
  • 2014-02-12
  • 2019-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多