【问题标题】:any way to loop iteration with same item in python?有什么方法可以在python中使用相同的项目循环迭代?
【发布时间】:2009-04-01 14:36:46
【问题描述】:

在没有收到下一项的情况下循环迭代是一种常见的编程任务。例如:

for sLine in oFile :
  if ... some logic ... :
    sLine = oFile.next()
    ... some more logic ...
    # at this point i want to continue iteration but without
    # getting next item from oFile. How can this be done in python?

【问题讨论】:

  • -1:这令人费解。也许你想要一个“GOTO”?或者您可能需要定义一些可以重复使用的函数来避免这种人为的循环?

标签: python iterator


【解决方案1】:

我一开始以为你想要 continue 关键字,但这当然会让你得到下一行输入。

我想我很难过。循环遍历文件的行时,如果继续循环而不获取新行,究竟会发生什么?

您要再次检查生产线吗?如果是这样,我建议添加一个内部循环,该循环一直运行直到您“完成”输入行,然后您可以将其 break 退出,或者使用 while-condition 和一个标志变量来终止。

【讨论】:

  • +1:我也很困惑,有人指望文件迭代器继续下一次迭代而不读取下一行:-)
【解决方案2】:

只需创建一个您自己的迭代器,它可以让您将数据推回到流的前面,这样您就可以给循环一个您想再次查看的行:

next_lines = [] def prependIterator(i): 而真: 如果 next_lines: 产量(next_lines.pop()) 别的: 产量(i.next()) 对于 prependIterator(oFile) 中的 sLine: 如果...一些逻辑...: sLine = oFile.next() ...更多的逻辑... # 将行放回去以便读取 # 再次回到“for” # 陈述 next_lines.append(sLine)

如果 prepend_list 从未被触及,那么 prependIterator 的行为与它所传递的任何迭代器完全相同:内部的 if 语句将始终为 False,并且它只会放弃它已传递的迭代器中的所有内容。但是,如果在迭代期间的任何时候将项目放置在 prepend_list 上,那么这些项目将首先被生成,而不是在返回到从主迭代器读取之前。

【讨论】:

    【解决方案3】:

    您需要的是一个简单的、确定性的finite state machine。像这样的...

    state = 1
    for sLine in oFile:
       if state == 1:
          if ... some logic ... :
             state = 2
       elif state == 2:
          if ... some logic ... :
             state = 1
    

    【讨论】:

    • 在 python 中没有其他方法?状态机是一个不错的选择,但需要更多代码:(
    • 我可能遗漏了一些东西。这如何帮助用户将对象放回其可迭代对象的前面以供重新使用?
    • 放回一个对象不是问题。把一个物体放回去是一个问题的解决方案。这不是一个好的解决方案。如果是这样,那么编程语言将提供一种轻松处理它的方法。从 CE 的角度来看,FSM 是更好的解决方案。
    【解决方案4】:

    丑陋。将主体包裹在另一个循环中。

    for sLine in oFile :
      while 1:
        if ... some logic ... :
          sLine = oFile.next()
          ... some more logic ...
          continue
        ... some more logic ...
        break
    

    稍微好一点:

    class pushback_iter(object):
        def __init__(self,iterable):
            self.iterator = iter(iterable)
            self.buffer = []
        def next(self):
            if self.buffer:
                return self.buffer.pop()
            else:
                return self.iterator.next()
        def __iter__(self):
            return self
        def push(self,item):
            self.buffer.append(item)
    
    it_file = pushback_iter(file)
    for sLine in it_file:
        if ... some logic ... :
            sLine = it_file.next()
            ... some more logic ...
            it_file.push(sLine)
            continue
        ... some more logic ...
    

    不幸的是,没有简单的方法可以引用当前的迭代器。

    【讨论】:

    • 这看起来是一个不错的解决方案——不像我提出的关于使用生成器的建议那么紧凑,但仍然是使用相同逻辑的东西,并且是这里为数不多的真正解决问题的答案之一提问者的问题。
    【解决方案5】:

    您可以将 file.readlines() 放入列表中,而不是逐行循环遍历文件。然后遍历列表(如果需要,您可以查看下一个项目)。示例:

    list = oFile.readlines()
    for i in range(len(list))
        #your stuff
        list[i] #current line
        list[i-1] #previous line
        list[i+1] #next line
    

    您只需使用 [i-1] 或 [i+1] 即可转到上一行或下一行。你只需要确保无论如何,我都不会超出范围。

    【讨论】:

    • 这是一种在通过 for in list 迭代列表时向后移动一个元素的方法吗?在文本解析中,如果您累积行直到找到不适合的行并且您需要再次检查该行,这是一项常见任务
    • @eye of hell:如果您有一个特定的用例,请用您在该用例中尝试完成的内容的描述更新问题。
    • 请注意,即使您使用此方法,我仍将重置为下一个数字,因此您还需要从列表中删除下一个条目(这很昂贵)。
    • @eye of hell:如果不使用 for 循环,而是使用 while 循环并根据需要手动增加或减少索引。
    【解决方案6】:

    您只需要从迭代器中创建一个变量,然后对其进行操作:

    % cat /tmp/alt-lines.py
    #! /usr/bin/python -tt
    
    import sys
    
    lines = iter(open(sys.argv[1]))
    for line in lines:
        print line,
        lines.next()
    
    % 猫 /tmp/test
    1
    2
    3
    4
    % /tmp/alt-lines.py /tmp/test
    1
    3
    

    ...请注意,在这种情况下,我们无条件地执行 lines.next() ,因此对于奇数行的文件,上述操作会失败,但我认为您不会出现这种情况(并且添加错误检查是相当微不足道——只需在手册 .next()) 上捕获并丢弃 StopIteration。

    【讨论】:

      【解决方案7】:

      您可以将迭代器分配给一个变量,然后使用 .next 获取下一个。

      iter = oFile.xreadlines() # is this the correct iterator you want?
      try:
        sLine = iter.next()
        while True:
          if ... some logic ... :
            sLine = iter.next()
            ... some more logic ...
            continue
          sLine = iter.next()
      except StopIterator:
        pass
      

      【讨论】:

      • readlines() 不是迭代器。它返回一个列表,并且列表没有“next()”属性。
      【解决方案8】:

      jle 的方法应该可行,尽管您不妨使用 enumerate():

      for linenr, line in enumerate(oFile):
          # your stuff
      

      【讨论】:

        猜你喜欢
        • 2014-02-13
        • 2011-07-29
        • 2014-09-01
        • 2019-05-05
        • 1970-01-01
        • 2013-12-22
        • 2015-05-08
        • 2014-12-13
        • 2020-11-27
        相关资源
        最近更新 更多