Python - 使用嵌套for循环在一个CSV文件中搜索字符串

时间:2017-05-23 11:14:34

标签: python string csv search nested-loops

我是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循环做   步骤遍历inputfile的所有行。这是第二个嵌套的for循环,它只进行一次迭代过程。并且由于它到达终点,当第一个for循环迭代时,它不再执行任何迭代。

示例文件

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

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

  • MainFile:包含产品信息列表(SerialNumber,ModelNumber,Text Infos)

  • InputFile:包含我试图在MainFile中找到的SerialNumbers列表

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

类型:SerialNumber [varchar(64)],ModelNumber [(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)行)

类型:SerialNumber [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头进行比较,但是"问题"并非如此重要。

我在哪里弄错了?

感谢您的帮助。

1 个答案:

答案 0 :(得分: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]

这里我使用 set comprehension (花括号)来填充来自ifreader的值的集合。之后,使用in运算符可以轻松检查特定值的集合。

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

import codecs

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

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