【问题标题】:two for loops, second only executes on first iteration python两个for循环,第二个只在第一次迭代python时执行
【发布时间】:2013-02-06 20:17:22
【问题描述】:

我是一个 python 菜鸟,我正在尝试比较两个文件中的行之间的值,如果行在第二个文件中,则输出“行名”,后跟 1,如果行中缺少行,则输出 0第二个文件。第一次迭代返回 1,因为该行在第二个文件中,但对于剩余 > 1,000 行,无论它们是否在第二个列表中,它们都返回 0。似乎第二个“for循环”只在第一次迭代时执行。关于为什么的任何想法?这是我的代码:

    import sys  

    file1 = sys.argv[1] 

    file2 = sys.argv[2]

    name = str(file2)

    f1 = open(file1, 'r') 
    f2 = open(file1, 'r')
    o1 = open((name + '1.txt'), 'w')

    for line in f1:
        name = line.strip('\r\n')
        count = 0
        for line1 in f2:
            if name == line1.strip('\r\n'):
                count += 1
                print (str(name) + '\t' + str(1))
                o1.write(str(name) + '\t' + str(1) + '\r\n')
        if count == 0:
            print (str(name) + '\t' + str(0))
            o1.write(str(name) + '\t' + str(0) + '\r\n')

    f1.close()
    f2.close()
    o1.close()
Any help is very much appreciated!

经过一些更改,这就是我所拥有的,它只返回'1s'

f1 = open(file1, 'r') #opens files for reading
f2 = open(file2, 'r')
o1 = open((name + '1.txt'), 'w')

f2s = {line.strip('\n') for line in f2}

for line in f1:
    line = line.strip('\n')
    count = 0
    if line in f2s:
        count += 1
        print (str(line) + '\t' + str(1))
        o1.write(str(line) + '\t' + str(1) + '\n')
    if count == 0:
        print (str(line) + '\t' + str(0))
        o1.write(str(line) + '\t' + str(0) + '\n')

尴尬,我打开同一个文件两次。菜鸟。

【问题讨论】:

  • 几个cmets:name已经是一个字符串,所以不需要str(name)。同样,"1"str(1) 更好。然后,\n 是 Python 中的换行符;它会在 Windows 上自动将其转换为 \r\n,因此无需这样做(这样做甚至可能会受到伤害)。
  • @TimPietzcker:+1。除非您在 Unix 上阅读 Windows 文本文件,否则它可能会很有用。 (但是 OP 看起来他正在使用 Py3,所以有更好的方法来做到这一点。)
  • 另外,你可能指的是f2 = open(file2),而不是f2 = open(file1),对吧?否则,f1 中的每一行也在 f2 中,因为它们是同一个文件……并且您应该考虑使用 with open(file1) as f1, open(file) as f2: 而不是显式的 close 语句,因为它更容易阅读且更难出错。

标签: python for-loop


【解决方案1】:

f2 是你的第二个文件的迭代器,当它被读取时,它就用完了。

可以重置迭代器 f2.seek(0, 0),但这并不是最好的方法。

最好将f2 中的所有值放入set,然后只对f1 进行一次迭代:

f2s = {line.strip('\n') for line in f2}

for line in f1:
    name = line.strip('\n') # No need for \r\n
    if name in f2s:
        # etc.

如果需要统计f1中每一行在f2中出现的次数,那么可以使用Counter

from collections import Counter
f2c = Counter(line.strip('\n') for line in f2)

for line in f1:
    name = line.strip('\n')
    if name in f2c:
        count = f2c[name]

【讨论】:

  • +1 用set.__contains__替换整个内循环。
  • @Tim 谢谢你的回复。我已经进行了更改,但是现在,当我运行我的代码时,它会返回所有值,即使我知道这些值并非全部在集合中。我已将更新后的代码添加到原始帖子中,有什么想法吗?
  • @Micrasema:你打开同一个文件两次。
  • @Tim,哇,太尴尬了,对不起。哎呀。你很有帮助
  • @Micrasema: abarnert 比我更早注意到这一点(请参阅他对您问题的第二条评论)。
【解决方案2】:

第一次执行for line in f2: 时,它会遍历f2 中的每一行,将当前文件指针留在文件末尾。所以,第二次,它从文件末尾开始,遍历所有剩余的 0 行……

如果你想重复这一点,有几种方法可以做到。您可以将f2 = open(file1, 'r') 移到外循环中。或者您可以使用f2.seek(0, 0) 重置文件。或者你可以使用itertools.tee

但是,除非您真的没有足够的内存一次保存整个文件,否则您可能希望第一次将这些行读入 list 并迭代 list

l2 = list(f2)
# ...
for line in f1:
    # ...
    for line1 in l2:
        # ...

【讨论】:

    【解决方案3】:

    标准库difflib 有助于比较行,也许您可​​以利用它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-13
      • 2019-01-05
      • 1970-01-01
      • 2010-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-05
      相关资源
      最近更新 更多