【问题标题】:Why does this nested for-loop iterate twice over the second loop, and not at all afterwards?为什么这个嵌套的 for 循环在第二个循环中迭代了两次,之后就完全没有了?
【发布时间】:2019-04-16 06:46:09
【问题描述】:

我正在尝试通过下面定义的函数运行它来处理一些数据。它似乎可以很好地运行程序,但是循环不会迭代我期望的次数。

我将 return 语句放在哪里似乎并不重要,只要它在函数内部而不是在 if 语句之下。

我尝试在每个 for 循环下独立编写行,它在每种情况下写入预期的行数。

def _ManhattanDistance(x,y):
    a = 0
    for i in range(0,len(x)):
        a += abs(float(x[i])-float(y[i]))
    return a

def _CabFare(x,y,z):
    with open(x, 'r') as f:
        with open(y, 'r') as g:
            with open(z, 'wb') as h:
                reader_1 = csv.reader(f)
                reader_2 = csv.reader(g)
                writer = csv.writer(h)
                for row_b in reader_2:
                    for row_a in reader_1:
                        if _ManhattanDistance(row_a,row_b) > 0:
                            writer.writerow(row_a)
                            writer.writerow(row_b)
                return

作为参考,假设我的输入 reader_1 应该有 200 行,而 reader_2 应该有 17145 行。由于我们的包含阈值为零,我预计输出文件中有 17145*200 = 3429000 行 - 我得到的是一个 400 行的输出。

【问题讨论】:

  • 我认为,我们需要查看一些示例数据来了解发生了什么。 FWIW,我认为您根本不需要 return 声明。
  • 数据集的元素是相当长的向量,我有一种感觉,包括其中一些可能最终会比不包含更令人困惑。您对第二个 return 语句是正确的-它现在被丢弃了。谢谢!

标签: python csv


【解决方案1】:

这似乎有效:

from itertools import product

def _CabFare(x,y,z):
    with open(x, 'r') as f, open(y, 'r') as g, open(z, 'wb') as h:
        writer = csv.writer(h)
        for row_a, row_b in product(csv.reader(f), csv.reader(g)):
            if _ManhattanDistance(row_a, row_b) > 0:
                writer.writerow(row_a)
                writer.writerow(row_b)

速度较慢,但​​内存占用较少:

def _CabFare(x,y,z):
    with open(x, 'r') as f, open(z, 'wb') as h:
        writer = csv.writer(h)
        for row_a in csv.reader(f):
            with open(y, 'r') as g:
                for row_b in csv.reader(g):
                    if _ManhattanDistance(row_a, row_b) > 0:
                        writer.writerow(row_a)
                        writer.writerow(row_b)

【讨论】:

  • 不过可能会占用一些内存。
  • 您介意解释一下为什么这两个版本之间存在差异吗?据我了解with 容器和csv.reader 行生成器,一次只加载一行,所以这两个版本对我来说似乎相当有效。
  • 第一个使用itertools.product() 并且只会读取两个输入文件一次 - 至少将其中一个保存在内存中。第二个重新读取第一行中每一行的第二个 CSV。大量重复读取正在进行,但它一次只能在内存中保存 2 行,因此内存使用率很低。
  • 谢谢。这段代码似乎更接近 - 输出中的行数是我预期的两倍。我会试着弄清楚为什么会这样,但这似乎与我正在寻找的足够接近。非常感谢!
  • 我们正在为两个输入文件中的每个行组合编写 两个 行 - 可能是这样吗?
【解决方案2】:

reader 是一个有状态的迭代器。一旦你用尽它,它就完成了,你需要重新打开它才能再次迭代文件:

def _CabFare(x,y,z):
    with open(x, 'r') as f:
        with open(y, 'r') as g:
            with open(z, 'wb') as h:
                reader_2 = csv.reader(g)
                writer = csv.writer(h)
                for row_b in reader_2:
                    reader_1 = csv.reader(f) # Reopen reader_1 for each iteration
                    for row_a in reader_1:
                        if _ManhattanDistance(row_a,row_b) > 0:
                            writer.writerow(row_a)
                            writer.writerow(row_b)

【讨论】:

  • @DirtyBit 他们肯定是,但这对 OP 的问题无关紧要,所以我不想碰它。
  • 我尝试实现此代码,但仍然只返回 400 行。
猜你喜欢
  • 2017-02-12
  • 2023-01-30
  • 1970-01-01
  • 1970-01-01
  • 2019-08-29
  • 2019-03-26
  • 2016-03-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多