【问题标题】:Nested for loop only runs on first iteration嵌套 for 循环仅在第一次迭代时运行
【发布时间】:2019-12-19 09:09:17
【问题描述】:

我正在使用一个列表,并对照 csv 文件中保存的信息检查该列表。我试图一次做一个列表项,但是在初始迭代之后,嵌套的 for 循环似乎没有运行。

我使用了初始的 For 循环,因此整个循环将运行等于列表中项目数的迭代次数。然后内部 for 循环针对 csv 文件中的行数运行。如果列表项与 CSV 行中的信息匹配,则非常内部的 If 语句会起作用。

with open('MY_PATH', encoding="utf8") as csv_file:
    csv_reader = csv.reader(csv_file, delimiter=',') 
    line_count = 2
    for i in range(0, len(class_numbers)):
        for row in csv_reader:
            if obj_list[i]['name'] in row[1]:
                audiofile = '{}.mp3' .format(row[0][0:8])
                #audio = fetch_file(audiofile)
                print(row[1],'-' , audiofile)
                line_count += 1
            else:
                line_count += 1
                #print('error')

【问题讨论】:

    标签: python nested-loops


    【解决方案1】:

    您的 csv_reader 是可迭代的,但不是序列。这意味着,一旦它被创建,它只能被迭代一次(就像在你的 for 循环中一样)。之后,它就被耗尽了,任何进一步的迭代尝试都会将它视为空的。在被销毁和重新创建之前,它一直是空的。

    您可以做几件事。您可以在每个循环上重新创建 csv_reader。或者您可以将该文件的内容存储到一个序列中,例如一个列表——例如,您可以使用readlines。或者你可以交换你的两个循环——首先循环csv_reader,然后在里面循环range(0, len(class_numbers))。或者您可以通过csv_file.seek() 重置阅读器(感谢@Barmar 提供该选项。)每种方法都有其缺点。

    【讨论】:

    • 据我了解,csv_reader 实际上使用了底层的file 对象的迭代器。可以使用csv_file.seek() 重置。
    • @Barmar:是的,这是另一种可能性。我会将其添加到我的答案中。谢谢!
    【解决方案2】:

    csv.reader对象只能迭代一次,然后迭代器就用完了,没有“重置”回到csv开头的概念。

    您最有可能要做的是首先将 csv 转换为列表,以便您可以对其进行多次迭代:

    with open('MY_PATH', encoding="utf8") as csv_file:
        csv_reader = csv.reader(csv_file, delimiter=',')
        # turn csv_reader into a list of rows instead of a reader object
        cvs_rows = list(csv_reader) 
        line_count = 2
        for i in range(0, len(class_numbers)):
            # you can now iterate over the rows as many times as you like
            for row in csv_rows:
                if obj_list[i]['name'] in row[1]:
                    audiofile = '{}.mp3' .format(row[0][0:8])
                    #audio = fetch_file(audiofile)
                    print(row[1],'-' , audiofile)
                    line_count += 1
                else:
                    line_count += 1
                    #print('error')
    

    【讨论】:

    • 如果你使用csv_file.seek(0),它也会重置csv_reader