【问题标题】:Is it possible to skip a fixed number of iterations in a loop in Python?是否可以在 Python 的循环中跳过固定数量的迭代?
【发布时间】:2022-01-21 13:46:49
【问题描述】:

简介:

所以我知道已经有一个与我类似的问题 (Skip multiple iterations in loop) 有一个非常好的答案,但我仍有一些悬而未决的问题:


问题一:

没有迭代器有什么办法吗?

我正在寻找类似 * 3 的东西:
song = ['always', 'look', 'on', 'the', 'bright', 'side', 'of', 'life']

for sing in song:
    print(sing, end=" ")
    if sing == 'look':
        continue * 3

预期输出:

always look side of life 

问题2:

如果我必须使用迭代器对象,那么是否可以在固定的时间内完成它?

原来的问题有这样的解决方案:

song = ['always', 'look', 'on', 'the', 'bright', 'side', 'of', 'life']
song_iter = iter(song)
for sing in song_iter:
    print(sing)
    if sing == 'look':

        next(song_iter)
        next(song_iter)
        next(song_iter)

        print(next(song_iter))

但我希望它做到这一点,比如说 x = 5 次。这是不可能的:

song = ['always', 'look', 'on', 'the', 'bright', 'side', 'of', 'life']
song_iter = iter(song)
for sing in song_iter:
    print(sing)
    if sing == 'look':

        next(song_iter) * x

        print(next(song_iter))

那你会怎么做呢?我知道可以使用函数itertools.<b>islice</b>,但是有没有没有任何库的方法?


我的方法:

这很好用:

song = ['always', 'look', 'on', 'the', 'bright', 'side', 'of', 'life']
song_iter = iter(song)

skip_iterations = 3

for sing in song_iter:
    print(sing)
    if sing == "look":
        while skip_iterations > 0:
            next(song_iter, "")

            skip_iterations -= 1

输出:

always look side of life 

但也许其他人有更好的主意? :)


链接:

The Question I was mentioning - The Answer for that question

【问题讨论】:

  • 您的方法似乎足够好,除了我会使用for 循环:for _ in range(skip_iterations): next(song_iter)
  • 每个for 循环都使用一个迭代器,无论您是否意识到它。使用iter 只是让您可以在代码级别访问一个。无论如何,您的问题似乎是:给定一个迭代器对象,我们如何在其上调用next 指定次数?好吧 - 您如何通常在 Python 中执行指定次数的任何事情?使用... for 循环,对吗?所以....
  • "如果我必须使用迭代器对象,那么是否可以在固定的时间内完成它?" - 使用任意迭代器,不。迭代器是顺序的,而不是随机访问的。例如,链表上的迭代器如果不逐个跟踪链接就无法前进,而生成器甚至没有明确定义的元素,直到您运行它并使其一个一个产生元素。
  • 如果你只是迭代一个列表,那么你可以很容易地在恒定时间内跳过,但不能使用标准列表迭代器。您必须编写自己的处理方式。

标签: python loops for-loop iterator continue


【解决方案1】:

我会考虑“历史性”的迭代方式。

song = ['always', 'look', 'on', 'the', 'bright', 'side', 'of', 'life']

i = 0
while i < len(song):
    sing = song[i]
    i += 1

    print(sing, end=" ")
    if sing == 'look':
        i += 3
        continue

    # ... other code ...

【讨论】:

    【解决方案2】:

    问题 1

    您可以使用迭代绑定来跟踪何时可以在循环中恢复评估

    song = ['always', 'look', 'on', 'the', 'bright', 'side', 'of', 'life']
    
    iter_bound = -1
    for i, sing in enumerate(song):
        if i <= iter_bound:
            continue
        if sing == 'look':
            iter_bound = i + 3
        print(sing, end=" ")
    

    如果您在代码中经常使用它,您可能需要围绕它编写一个函数:

    from typing import Iterable, Callable
    
    def skip_n_on_condition(iterator: Iterable, condition: Callable, n_skips: int):
        """Loop over iterable and perform n_skips whenever the condition on the element is met"""
        iter_bound = -1
        for i, element in enumerate(iterator):
            if i <= iter_bound:
                continue
            if condition(element):
                iter_bound = i + 3
            yield element
        
    song = ['always', 'look', 'on', 'the', 'bright', 'side', 'of', 'life']
    
    print(*skip_n_on_condition(song, lambda x: x == 'look', 3), end=" ")
    

    问题 2

    既然您知道循环的次数,最好使用 for 循环。这也是一个不会改变您可能没有预料到的skip_iterations值的实现。

    song = ['always', 'look', 'on', 'the', 'bright', 'side', 'of', 'life']
    song_iter = iter(song)
    
    skip_iterations = 3
    
    for sing in song_iter:
        print(sing)
        if sing == "look":
            for _ in range(skip_iterations):
                next(song_iter, "")
    

    您可以使用列表推导使循环成为单行。

    song = ['always', 'look', 'on', 'the', 'bright', 'side', 'of', 'life']
    song_iter = iter(song)
    
    skip_iterations = 3
    
    for sing in song_iter:
        print(sing)
        if sing == "look":
            [next(song_iter, "") for _ in range(skip_iterations)]
    

    【讨论】:

      【解决方案3】:

      使用跳过计数器:

      song = ['always', 'look', 'on', 'the', 'bright', 'side', 'of', 'life']
      
      skip = 0
      for sing in song:
          if skip:
              skip -= 1
              continue
          print(sing, end=" ")
          if sing == 'look':
              skip = 3
      

      【讨论】:

        【解决方案4】:

        另一种方法是使用具有更完整更新逻辑的 C 风格 for 循环:

        def cfor(i, test_i, update_i):
            while test_i(i):
                yield i
                i=update_i(i)
        
        song = ['always', 'look', 'on', 'the', 'bright', 'side', 'of', 'life']
        
        skip=3
        
        for i in cfor(0, 
                      lambda i: i<len(song), 
                      lambda i: i+skip+1 if song[i]=='look' else i+1):
            print(song[i], end=' ')
        

        或者,这可以只是一个while 循环:

        idx=0
        while(idx<len(song)):
            print(song[idx], end=' ')
            idx+=skip+1 if song[idx]=='look' else 1
        

        如果您的skip 很大,那么其中任何一个都会更快。


        您也可以将enumerate 与理解一起使用:

        l=song.index('look')
        ' '.join([w for i,w in enumerate(song) if i<=l or i>(l+skip)])
        

        【讨论】:

          【解决方案5】:

          Ans 1 有很多方法可以解决这个问题,其中最简单的一种方法是检查索引,例如

          song = ['always', 'look', 'on', 'the', 'bright', 'side', 'of', 'life']
          skip_iterations=3
          for i,sing in enumerate(song):
              if not song.index('look') < i < song.index('look')+skip_iterations+1:
              print(sing, end=" ")
          

          'enumerate' 返回(索引,元素) Ans 2 您的方法很好,您可能更喜欢 for 循环而不是 while 循环,但这只是个人建议。

          【讨论】:

            猜你喜欢
            • 2016-10-15
            • 1970-01-01
            • 2013-12-14
            • 2013-05-21
            • 2021-08-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多