【问题标题】:Python - Search strings in one CSV file with nested for-loopPython - 使用嵌套 for 循环在一个 CSV 文件中搜索字符串
【发布时间】:2017-10-23 07:30:35
【问题描述】:

我是 stackoverflow 和学习 python 的新手。

如果使用 Python 在一个 CSV 文件中搜索多个字符串(取自输入文件),我遇到了一些麻烦。

基本上,我的 python 代码从输入文件 (inputfile.csv) 中一个接一个地获取字符串,并搜索每个字符串是否位于另一个名为 mainfile.csv 的文件的第一列中。它只与包含我要查找的相关数据的 mainfile.csv 的第一列进行比较。

注意:文件非常大,mainfile.csv 有超过 100 万行(并且还在增长),而 inputfile.csv 通常大约有 30,000 行。

这里是代码。

#!/usr/bin/python
import csv

mainfile = open('mainfile.csv', 'rb')
inputfile = open('inputfile.csv', 'rb')

mfreader = csv.reader(mainfile, delimiter=',') # mainfile reader
ifreader = csv.reader(inputfile) # inputfile reader, just one column, no delimeter

for ifrow in ifreader:
    for mfrow in mfreader:
        if ifrow[0] == mfrow[0]:
            print ifrow[0], mfrow[0] # This line is a print for debugging purpose
            print "Found a match for : %s " % ifrow[0]
            perform_some_operations()
        else:
            print ifrow[0], mfrow[0] # This line is a print for debugging purpose
            continue

mainfile.close()
inputfile.close()

问题: “嵌套 for 循环”仅在 inpufile 的第一行中执行。它“忽略” inputfile.csv 的其他行。

编辑

其实我对这个问题的理解是错误的。第一个 for 循环 do 遍历输入文件的所有行。这是第二个嵌套的 for 循环,它只经过一次迭代过程。并且由于它到达了末尾,所以当第一个 for 循环迭代时,它不再执行任何迭代。

示例文件

以下是一些示例文件。出于示例的目的,“行值”被简化了。

基本上,我们处理 2 个文件:

  • MainFile : 包含产品信息列表(序列号、型号、文本信息)

  • InputFile:包含我试图在 MainFile 中查找的序列号列表

MainFile(mainfile.csv,文件大小:> 1,000,000 (1M) 行)

类型:序列号[varchar(64)]、型号[(varchar(64)]、信息[varchar(2048)]

SerialNumber, ModelNumber, Informations
SN111aaa, MN123425, Informations for SN111aaa
SN222bbb, MN123425, Informations for SN222bbb
SN333ccc, MN456789, Informations for SN333ccc
SN444ddd, MN654321, Informations for SN444ddd
SN555eee, MN123425, Informations for SN555eee

InputFile(inputfile.csv,文件大小:~30,000 (30K) 行)

类型:序列号[varchar(64)]

SN000xyz
SN111xyz
SN222xyz
SN333xyz
SN444ddd

在上面的例子中,由于 SN444ddd 是唯一可以在 inputfile 和 mainfile 中找到的字符串,我的 python 代码应该返回我(如果我们关闭调试行):

Found a match for SN444ddd

然后我可以执行一些操作。

但事实并非如此。我从调试打印行得到的是:

$ ./myprogram.py
SN000xyz SerialNumber
SN000xyz SN111aaa
SN000xyz SN222bbb
SN000xyz SN333ccc
SN000xyz SN444ddd
SN000xyz SN555eee
$

只处理输入文件的第一行。

编辑错误。参看。以前的编辑。

它还与 mainfile.csv 标头进行比较,但“问题”并不重要。

我哪里弄错了?

感谢您的帮助。

【问题讨论】:

  • 绝对不是 CSV 的东西。这是 pandas 的工作,理想情况下是数据库
  • 去掉“继续”。在第一个“if”分支中包含一个“break”。
  • @HubertGrzeskowiak 即使你这样做了,我们也在这里看到了 3000 万次迭代。
  • 我同意@e4c5,但现在我不具备实现熊猫或数据库的知识。这将是下一步 (db)。

标签: python string csv search nested-loops


【解决方案1】:

主要问题似乎是ifreadermfreaderiterators,这意味着一旦他们用尽了可用项目列表,就不会重新开始。

第二个问题是您的方法效率很低。与其在内部循环中一次又一次地通过迭代器,我建议从inputfile.csv 中创建一个序列号set。集合不能包含重复值,并且它们可以非常有效地检查值的存在。

所以您的代码可能如下所示:

#!/usr/bin/python
import csv

def perform_some_operations():
    # ...
    pass

with open('inputfile.csv', 'rb') as inputfile:
    ifreader = csv.reader(inputfile) # inputfile reader, just one column, no delimeter
    serial_numbers = {row[0] for row in ifreader}

with open('mainfile.csv', 'rb') as mainfile:
    mfreader = csv.reader(mainfile, delimiter=',') # mainfile reader

    for row in mfreader:
        if row[0] in serial_numbers:
            print "match for    : %s " % row[0]
            perform_some_operations()
        else:
            print "NO MATCH for : %s " % row[0]

这里我使用了一个集合理解(花括号)用来自ifreader 的值填充集合。之后,很容易使用 in 运算符检查集合中的特定值。


注意 - 不要使用'rb' 模式来读取文件,而应该使用codings 模块并在打开文件时指定文件编码。

import codecs

with codecs.open('inputfile.csv', 'r', encoding='utf8') as inputfile:
    ...

使用与您的源数据匹配的正确encoding 参数。在 Python 3 中,open() 函数本身支持 encoding 参数,在 Python 2 中,该模块可以提供帮助。

【讨论】:

  • 是的,你是对的。我刚刚在这里找到了类似的问题答案stackoverflow.com/questions/31336443/…
  • @XavierR。不,这个答案根本不相似。它建议您不应该做的事情 - 在外循环的 每个循环迭代 中打开并迭代第二个 CSV 文件。这是一种不好的方法,不要那样做。
  • Tomalak,您的解决方案非常完美,谢谢。关于我的第一条评论,我的意思是对我的问题的类似回答。正如您正确陈述的那样,建议的解决方案效率非常低,尽管它解释了嵌套的 for 循环如何有效地处理 csv 文件。无论如何,非常感谢您的帮助!
  • Tomalak 如果您不介意,我还有一个问题。当我尝试使用@yourname 开始评论以指定我要回复的人时,当我单击“添加评论”按钮时,[at]yourname 会消失。知道为什么会这样吗?
  • 是的,那是因为当您对我的任何帖子发表评论时,我会收到通知无论如何 - 无需明确@-提及我。
猜你喜欢
  • 2015-04-25
  • 1970-01-01
  • 2016-11-15
  • 2014-01-29
  • 2018-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多