【问题标题】:csv dictionary does not reset to the beginning when looping through it multiple timescsv字典在多次循环时不会重置到开头
【发布时间】:2018-11-15 06:22:50
【问题描述】:

我正在循环一个 CSV 文件,该文件作为字典打开。问题是,当我遍历字典中的行时,主 for 循环转到下一项。运行for 循环时,字典不会重置为第一项。所以如果它到达最后一行,它不会改变。

names = ['a', 'b', 'c', 'd', 'e', 'f']
source1_csv = open("output.csv", mode='r')
dictionary_csv = csv.DictReader(source1_csv)

for letters in names:
    for entry in dictionary_csv:
        print(entry["name"])
        if entry['name'] == letters:
            print("found it")

您可以使用任何 CSV 文件,只需替换 entry 中的键,并注意如果外部 for 循环中没有匹配项,一旦选择了 names 中的下一项,字典的内部 for 循环将退出,因为字典已经在最后一个位置并且不会重置。

我该如何避免这种情况,所以字典的位置会被重置并解析名称列表中每个条目的每一行?

【问题讨论】:

    标签: python csv


    【解决方案1】:

    csv 不提供重置迭代器的方法,但文件对象接口提供。您可以使用file.seek(0) 将文件重置为其起始位置。

    names = ['a', 'b', 'c', 'd', 'e', 'f']
    source1_csv = open("output.csv", mode='r')
    
    for letters in names:
        source1_csv.seek(0)
        for entry in csv.DictReader(source1_csv):
            print(entry["name"])
            if entry['name'] == letters:
                print("found it")
    

    当然,您也可以将条目存储在列表中,并根据需要进行多次迭代。但这不适用于文件太大而无法存储在内存中。

    【讨论】:

      【解决方案2】:

      解决方案 1

      从您上面的代码来看,您似乎不需要多次迭代整个 csv,您可以像这样切换循环:

      for entry in dictionary_csv:
          for letters in names:
              print(entry["name"])
              if entry['name'] == letters:
                  print("found it")
      

      dictionary_csv 的循环切换到外循环将避免多次循环遍历 csv。

      解决方案 2

      但是如果你不想改变循环的顺序,你可以简单地将DictReader 转换为list,然后再自己使用它。这样,list 将消耗阅读器,并返回它的列表,您可以对其进行多次迭代:

      dictionary_csv = list(csv.DictReader(source1_csv))
      

      但如果您的 csv 相当大,则不建议使用它创建列表,因为列表大小会很大。

      解决方案 3

      除了创建一个列表,你还可以在内循环之前寻找源文件source1_csv到0:

      for letters in names:
          source1_csv.seek(0)
          for entry in dictionary_csv:
              print(entry["name"])
              if entry['name'] == letters:
                  print("found it")
      

      它将源文件从头开始,dictionary_csv 会再次为您读取。

      编辑

      正如@merlyn 在下面的 cmets 中指出的那样,解决方案 3 将无法完全正常工作,因为在寻求 0 之后,dictionary_csv 会将 csv(标题)的第一行解释为单独的数据行。所以,你必须在寻求 0 之后忽略一行。

      source1_csv.seek(0)
      source1_csv.readline()
      

      或者,每次搜索 source1_csv 时重新实例化 dictionary_csv(为此,您可以在下面查看 @merlyn 的答案)。

      【讨论】:

      • 谢谢!一旦我将其转换为列表,它就可以工作。有没有办法迭代或重置字典的“索引指针”?只是想知道是否有办法这样做。
      • 是的,有一种方法,你实际上必须将source1_csv 搜索到0,然后DictReader 会为你重新读取。
      • @MuhammadAhmad 解决方案 3 中有一个小错误。如果每次查找文件开头时都没有重新实例化 dictionary_csv,它会将 csv 文件的标题解释为常规条目。跨度>
      • 是的,感谢您指出。我之前没有注意到。让我纠正一下。
      • @merlyn 已更正。谢谢。 dictionary_csv 将标题行作为单独的数据行是正确的,但不是重新实例化它,另一种变体可能是忽略第一行。
      猜你喜欢
      • 2014-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-30
      • 1970-01-01
      • 2020-04-06
      • 2020-11-10
      • 1970-01-01
      相关资源
      最近更新 更多