【问题标题】:nested for loop in python not workingpython中的嵌套for循环不起作用
【发布时间】:2012-10-22 03:29:18
【问题描述】:

我们基本上有一个很大的 xcel 文件,我想做的是创建一个列表,其中包含每列的最大值和最小值。有 13 列,这就是为什么 while 循环在达到 14 时应该停止的原因。问题是一旦计数器增加,它似乎就不会遍历 for 循环一次。或者更明确地说,while 循环只经过一次 for 循环,但它似乎确实在循环,因为它将计数器增加 1 并在 14 处停止。应该注意,输入文件中的行是数字字符串,即为什么我将它们转换为元组,然后检查给定位置的值是大于 column_max 还是小于 column_min。如果是这样,我重新分配 column_max 或 column_min。一旦完成,column_max 和 column_min 将附加到列表(l)中,并且计数器(位置)增加以重复下一列。任何帮助将不胜感激。

input_file = open('names.csv','r')
l= []  
column_max = 0
column_min = 0
counter = 0
while counter<14:
    for row in input_file:
        row = row.strip()
        row = row.split(',')
        row = tuple(row)
        if (float(row[counter]))>column_max:
            column_max = float(row[counter])  
        elif (float(row[counter]))<column_min:
            column_min = float(row[counter])    
        else:
            column_min=column_min
            column_max = column_max
    l.append((column_max,column_min))
    counter = counter + 1

【问题讨论】:

  • 使用for i in range(14) 而不是while 循环。此外,您可能希望使用csvreader 而不是由, 分割:csvreader 将处理包含逗号的字符串。
  • 如果有 13 列,您将使用 13 作为边界值,而不是 14
  • 我会使用column_max = float('-inf')column_min = float('inf') 而不是column_max = 0column_min = 0。这样你知道最大值和最小值是正确的。

标签: python


【解决方案1】:

我认为您想切换 forwhile 循环的顺序。

请注意,有一个稍微更好的方法来做到这一点:

with open('yourfile') as infile:
    #read first row.  Set column min and max to values in first row
    data = [float(x) for x in infile.readline().split(',')]
    column_maxs = data[:]
    column_mins = data[:]
    #read subsequent rows getting new min/max
    for line in infile:
        data = [float(x) for x in line.split(',')]
        for i,d in enumerate(data):
            column_maxs[i] = max(d,column_maxs[i])
            column_mins[i] = min(d,column_mins[i])

如果您有足够的内存一次将文件保存在内存中,这将变得更加容易:

with open('yourfile') as infile:
    data = [map(float,line.split(',')) for line in infile]
    data_transpose = zip(*data)
    col_mins = [min(x) for x in data_transpose]
    col_maxs = [max(x) for x in data_transpose]

【讨论】:

  • 仅仅交换两个循环是不够的; row = 行也需要从内部循环中取出。但你说得很对:minmax 是正确的做法。
  • 这取每行的最大值,但问题中的代码旨在计算每列的最大值。否则 +1。
  • @ChrisMorgan -- 是的,相关的逻辑也应该被移动。我认为这很明显......
  • @BrianL -- 很好的收获。相应更新。
  • “我认为你想切换forwhile 循环的顺序”:不,他没有……这是对问题的转置解释的遗物。
【解决方案2】:

一旦你消费了文件,它就被消费了。因此,再次对其进行迭代不会产生任何结果。

>>> for row in input_file:
...     print row
1,2,3,...
4,5,6,...
etc.
>>> for row in input_file:
...     print row
>>> # Nothing gets printed, the file is consumed

这就是您的代码无法正常工作的原因。

然后您有三种主要方法:

  1. 每次读取文件(I/O操作效率低下);
  2. 将其加载到列表中(对于大文件效率低下,因为它将整个文件存储在内存中);
  3. 重新编写逻辑以逐行操作(相当可行和高效,虽然在代码中不如将其全部加载到二维结构中并转置它并使用minmax 可能是)。

这是我对第三种方法的技术:

maxima = [float('-inf')] * 13
minima = [float('inf')] * 13
with open('names.csv') as input_file:
    for row in input_file:
        for col, value in row.split(','):
            value = float(value)
            maxima[col] = max(maxima[col], value)
            minima[col] = min(minima[col], value)

# This gets the value you called ``l``
combined_max_and_min = zip(maxima, minima)

【讨论】:

  • 我对此的唯一不满是您基本上硬编码了列数,而我的这个实现版本没有硬编码列数。 (另外,不需要row.strip(),因为float 不关心空格)。
  • @mgilson:没有硬编码也可以处理,但更丑。作为参考,这类似于float('-inf') if col &gt; len(maxima) else maxima[col]。或者复制行读取代码。总而言之,我认为对值进行硬编码通常(尽管并非总是)更合适。至于row.strip()这个业务,我想了想,但因为懒惰而留了下来。您现在已提示我删除它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-03
  • 1970-01-01
  • 2021-05-10
  • 2016-10-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多