【问题标题】:Python, nested for loopPython,嵌套 for 循环
【发布时间】:2012-06-27 22:59:54
【问题描述】:

我是 python 新手,在实现嵌套的“for 循环”时遇到了困难。这可能很简单,但我尝试的以下示例代码并没有给我预期的结果。我的任务实际上是从属性表(ArcGIS 要素数据)中读取记录,并将其与 CSV 文件中的每条记录进行比较。但最初我试图对 2 个 CSV 文件做同样的事情,然后将类似的逻辑应用于我原来的问题。我试图弄清楚循环的工作原理,我可以稍后添加比较条件。任何帮助是极大的赞赏。谢谢。

这个想法是文件 1(CSV) 中的第一行将自身与文件 2(CSV) 中的所有行(逐行)进行比较,然后文件 1 中的第二行执行相同操作,直到文件 1 的每一行都进行比较本身到文件 2 中的所有行。所以在预期的结果中,我试图查看文件 1 中的每一行是否考虑了文件 2 中的每一行。

例子:

**File 1   File 2**
ALPHA      All
BETA       Bell
GAMMA      Cell
DELTA      Dell
ITA 

示例代码:

import csv, sys, os, string 
table1 = os.path.join(path, 'table1.csv')
table2 = os.path.join(path, 'table2.csv')
file1 = csv.reader(open(table1, 'r'))
file2 = csv.reader(open(table2, 'r'))
for row in file1:
    print row
    for prow in file2:
        print prow

预期结果:

   ALPHA
    All
    Bell
    Cell
    Dell

    BETA
    All 
    …..

    ITA

All
..
Dell

【问题讨论】:

  • 那么,问题是什么?
  • @Marcin:我试图看看应该如何格式化循环以达到预期的结果。@Jonas Wielicki 建议的解决方案奏效了。
  • @aglassman:当我尝试时,它只会显示file2的内容一次,然后打印file1的内容

标签: python csv for-loop


【解决方案1】:

这里的问题是,file2 is just a one-shot iterator。因此,在对file2 进行一次迭代之后(在file1 的第一次迭代中),您将完全耗尽数据。

相反,您必须将file2 的内容存储在一个列表中:

file2=list(csv.reader(open(table2,'r')))
for row in file1:
     print row
     for prow in file2:
         print prow

这将为您打印一些列表,所有这些列表仅包含一个元素,即相应行的第一个单元格。这是由于将文件解析为 CSV。每次迭代都会为您提供行中的单元格列表。

【讨论】:

  • 查看我的答案以获取示例。另外,我强烈建议将您的示例作为有效的 python。
  • @Jonas Wielicki:谢谢。这给了我预期的结果。我不知道一次性迭代器。我认为每次循环运行时它都会再次检查数据。
【解决方案2】:

这是因为当您迭代 csv.reader 对象时,每次迭代它都会变为空。

这就是 file2 迭代器的行为方式。

要解决这个问题,您应该首先将来自file2 的值保存在一个列表中。

file1=csv.reader(open(table1,’r’))
file2=list(csv.reader(open(table2, 'r'))) #edited this
for row in file1:
...     print row
...     for prow in file2:
...         print prow

【讨论】:

  • -1 字符串会更好,因为它可以消除嵌套循环。
  • 我认为list(csv.reader(open(table2, 'r'))) 比基本上只复制迭代器内容的列表推导更具可读性。
【解决方案3】:

问题是,在你遍历 file2 的所有行之后,它的流被消耗掉了。没有什么可读的了。下一个 for 循环不会重新设置 csv.reader 对象,而是会识别出所有内容都已被读取和解析,因此无需再做任何事情。

解决方案可能包括:

file2_stream = open(table2, 'r')
for row in file1:
  print row
  file2_stream.seek(0)  # Reset file stream position
  file2 = csv.reader(file2_stream)  # Init CSV parsing
  for prow in file2:
    print prow

或者,您可以每次都重新打开文件:

for row in file1:
  print row
  file2 = csv.reader(open(table2, 'r'))
  for prow in file2:
    print prow

这显然会在每次外部迭代时解析第二个文件。如果文件与内存大小相比并不大,您可能希望对其进行一次解析,然后将结果作为列表存储在内存中:

file2_rows = list(file2)
for row in file1:
  print row
  for prow in file2_rows:
    print prow

【讨论】:

    【解决方案4】:

    不要这样做。

    将第一个文件读入适当的数据结构(例如set),然后在读取第二个文件时,针对数据结构中收集的行进行测试。

    对于本练习,最好创建单个字符串,因为您似乎每次都打印从第一个文件读取的全部数据。

    file2='\n'.join((l[0] for l in csv.reader(open(table2,’r’))))
    for row in file1:
            print row
            print file2
    

    如果需要缩进,可以使用textwrapfile2添加缩进。

    【讨论】:

    • A set 不合适,因为它不保留排序(这可能是必要的)。 IE。它从初始数据集中删除信息。
    • @JonasWielicki 对于涉及比较的实际工作(这是 OP 所指的),几乎肯定需要一个集合。对于所描述的练习,字符串会好得多(每次都是一样的东西)。
    • 好的,同意。尽管如此,这并不是解决迭代枯竭的办法。我认为您至少应该在答案中提及顺序丢失,因为如果元素混合在一起,这确实是该特定循环中的意外结果。
    • @JonasWielicki 这正是耗尽迭代器的解决方案。这就是使用迭代器的原因——如果需要多次访问数据,则可以构建其他东西。
    • 不,至少在一般情况下不会,因为您正在丢弃以前可用的信息(订购)。我不认为稍后进行比较(这是 OP 似乎的目标)一组 可能 是合适的。但这不是一般情况。
    【解决方案5】:

    CSV 模块将为这两个文件返回迭代器,这些文件在循环后将被“使用”。这是文件的典型 Python 行为。

    为了在一个循环中将一个文件中的值用于另一个文件,您可以将它们加载到内存中。出于对您意图的最佳解读,我假设您希望将一个文件中的数据与另一个文件中的每一行相关联。我举一个说明性的例子:

    greek = csv.reader(open('file1.csv'))
    dells = csv.reader(open('file2.csv'))
    
    second_file_data = list(dells)
    
    #From here, dells is "spent."  If we would want to reuse it, we have to reopen it
    
    for line in greek:
      print line
      for other in second_file_data:
          print other
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-25
      • 2017-06-05
      • 2019-04-15
      • 2020-10-09
      • 2017-08-27
      • 2017-11-11
      相关资源
      最近更新 更多