【问题标题】:Cannot access parent for loop from nested for loop无法从嵌套的 for 循环访问父 for 循环
【发布时间】:2017-12-16 03:33:48
【问题描述】:

我正在尝试比较两个字典数组之间的索引值。为此,我使用了嵌套的 for 循环。当循环正确迭代时,firstDataSetNumber 没有在嵌套的 for 循环内进行迭代(由第二个 print 语句表示)。第一个打印语句显示 for 循环正在正确迭代。什么可能导致从嵌套 for 循环中的第二个 firstDataSetNumber 打印的值永远不会改变,即使它在第一个 print 语句中的值表明它确实在正确迭代?

def processCommandCenterFile(data):
    firstDataSet = data["FirstDataSet"]
    secondDataSet = data["SecondDataSet"]

    # Go through every First Data Set Record
    for firstDataSetRecord in firstDataSet:
        firstDataSetNumber = firstDataSetRecord["KeyOne"].strip()
        matchingSecondDataSetRecord = None

        print(firstDataSetNumber) # Always iterates properly throughout the application

        # Find the Second Data Set record with the KeyTwo number
        for secondDataSetRecord in secondDataSet:
            print(firstDataSetNumber) # Never iterates past the first value
            if secondDataSetRecord["KeyTwo"].strip() == firstDataSetNumber:
                matchingSecondDataSetRecord = secondDataSetRecord

data = {
    "FirstDataSet": CsvToDictionary("first_data_set.csv"),
    "SecondDataSet": CsvToDictionary("second_data_set.csv")
}

processCommandCenterFile(data)

我希望两个打印语句的输出相同。但是,当我运行它时,第一个打印语句是索引中的每个项目,但是第二个打印语句中的数据卡在列表中的第一个项目上。

FirstDataSet 和 SecondDataSet 键存储以下函数的输出,该函数加载 CSV 并将其转换为以 CSV 中的标题作为键的字典。

import csv

def CsvToDictionary(path):
    file = open(path, 'r')
    rawCsvArray = csv.reader(file, delimiter=',', quotechar='|')
    headers = rawCsvArray.next()
    dataDictionary = csv.DictReader(file, fieldnames=headers)

    return dataDictionary

这是用于制作FirstDataSet的CSV

KeyOne
143739629
143739629
143750196
143750196
143739646
143739646
143739661
143739661
143739718

然后是用于制作SecondDataSet的CSV

KeyTwo
143739629
143739629
143750196
143750196
143739646
143739646
143739661
143739661
143739718

【问题讨论】:

  • 如果你也能说出firstDataSetsecondDataSet中包含的内容以及你想要达到的结果会更有帮助。可能有更好的解决方案
  • 请将您的程序缩减为能够说明您的问题的最小的完整程序。请包括您的程序的实际和预期输出。请参阅minimal reproducible example 了解更多信息。
  • 你期望什么输出?从代码中的 cmets 来看,代码似乎工作正常。
  • 我希望两个打印语句的输出是相同的。但是,当我运行它时,第一个打印语句是索引中的每个项目,但是第二个打印语句中的数据卡在列表中的第一个项目上。
  • 哦,我认为如果secondDataSet 是一个迭代器(例如文件),而不是一个可以迭代多次的序列,你可能会得到一个奇怪的输出。迭代器(一般而言)是一次性使用的,因此您通常不能将其用作内部循环的目标。一些特定的迭代器可能会给你一种方法来回退它们(例如file.seek(0)),但这不是迭代器协议的正常部分。由于我们对data 一无所知,因此很难知道这是否是问题所在。

标签: python python-2.7 loops scope


【解决方案1】:

柯克兰回答了这个问题的实际解决方案。这里有一点上下文,如果其他人在这里结束的话。

问题在于csv.DictReader() 生成了一个DictReader 类型的实例,根据the docs,它“像普通阅读器一样运行。”
这意味着从 DictReader 读取值会耗尽实例的内容。
在第一轮内循环之后,secondDataSet 中什么都没有了。在未来的迭代中,内部循环没有任何要迭代的元素。

这可以通过在print 语句中添加标志来验证:

def processCommandCenterFile(data):
    ...
    for firstDataSetRecord in firstDataSet:
        ...
        print("first print:", firstDataSetNumber) 

    for secondDataSetRecord in secondDataSet:
        print("second print:", firstDataSetNumber) 
        ...

processCommandCenterFile(data)

输出:

('first print:', '143739629')
('second print:', '143739629')
('second print:', '143739629')
('second print:', '143739629')
('second print:', '143739629')
('second print:', '143739629')
('second print:', '143739629')
('second print:', '143739629')
('second print:', '143739629')
('second print:', '143739629')
('first print:', '143739629')
('first print:', '143750196')
('first print:', '143750196')
('first print:', '143739646')
('first print:', '143739646')
('first print:', '143739661')
('first print:', '143739661')
('first print:', '143739718')

正如柯克兰所说,最好的选择是将DictReader 转换为字典列表,例如,

list(csv.DictReader(file, fieldnames=headers))

(或者只使用 Pandas。)

【讨论】:

    【解决方案2】:

    我解决了这个问题(感谢 Blckknght),但是将 csv.DictReader 的输出转换为如下列表:

    import csv
    
    def CsvToDictionary(path):
        file = open(path, 'r')
        rawCsvArray = csv.reader(file, delimiter=',', quotechar='|')
        headers = rawCsvArray.next()
        dataDictionary = csv.DictReader(file, fieldnames=headers)
    
        return list(dataDictionary)
    

    【讨论】:

      【解决方案3】:

      第一个数据集编号看起来要在第二个开始之前声明。那么第二组中的每个人都应该查看第一个数据集

      【讨论】:

        猜你喜欢
        • 2018-07-13
        • 1970-01-01
        • 2014-03-11
        • 1970-01-01
        • 1970-01-01
        • 2015-01-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多