【问题标题】:Python -- Iterate an iterator twicePython——迭代一个迭代器两次
【发布时间】:2021-10-05 15:09:32
【问题描述】:

编辑:有一个similar question here 处理迭代器重置。然而,下面接受的答案解决了嵌套迭代器的实际问题,并处理了一个容易遗漏的问题,即嵌套迭代器不会重置。

有没有办法在 python 中对一个迭代器进行两次迭代?

在下面的示例代码中,我可以看到第二次迭代与第一次迭代在同一个对象上运行,因此产生了一个奇怪的结果。将此与下面的 C# 进行对比,产生我所追求的结果。

有什么方法可以做我想做的事。我想知道是否可以复制迭代器或“检索”它来自的函数,但也许有更简单的方法。 (我知道我可以在下面的玩具示例中调用 MyIter() 两次,但如果我不知道迭代器来自哪里并且不是我所追求的,那将毫无用处!)。

def MyIter():
  yield 1;
  yield 2;
  yield 3;
  yield 4;

def PrintCombos(x):
  for a in x:
      for b in x:
          print(a,"-",b);

PrintCombos(MyIter());

给予

1 - 2
1 - 3
1 - 4

对比:

static IEnumerable MyIter()
{
    yield return 1;
    yield return 2;
    yield return 3;
    yield return 4;
}

static void PrintCombos(IEnumerable x)
{
    foreach (var a in x)
        foreach (var b in x)
            Console.WriteLine(a + "-" + b);
}

public static void Main(String[] args)
{
    PrintCombos(MyIter());
}

这给出了:

1-1
1-2
1-3
1-4
2-1
2-2
. . .

【问题讨论】:

  • 您可以在 python 中无限次迭代迭代器。但是,如果您指的是生成器(从给出的代码来看,您就是这样),则无法在生成器本身上多次执行此操作。但是,您可以将生成器结果保存在内存中并对其进行迭代。在您给出的示例中,您可以通过调用 PrintCombos(list(MyIter()))
  • itertools.tee 可能就是您要找的。​​span>

标签: python for-loop iterator generator yield


【解决方案1】:

您可以使用itertools.tee 来创建生成器的多个副本

from itertools import tee

def MyIter():
    yield 1
    yield 2
    yield 3
    yield 4

def PrintCombos(x):
    it1, it2 = tee(x, 2)
    for a in it1:
        it2, it3 = tee(it2, 2)
        for b in it3:
        print("{0}-{1}".format(a, b))

PrintCombos(MyIter())

【讨论】:

    【解决方案2】:

    itertools.tee 从单个可迭代对象创建独立的迭代器。但是,一旦创建了新的迭代器,就不能再使用原来的迭代器了。

    import itertools
    def MyIter():
        yield 1;
        yield 2;
        yield 3;
        yield 4;
    
    def PrintCombos(x):
        xx = []
        xx.append(itertools.tee(x))
        n = 0
        for a in xx[0][0]:
            xx.append(itertools.tee(xx[n][1]))
            for b in xx[n+1][0]:
                print('%s - %s' % (a,b));
            n += 1
    
    PrintCombos(MyIter());
    

    【讨论】:

      【解决方案3】:

      我发现对这类问题使用列表推导最能有效地得到你想要的结果。

      x = [1,2,3,4]
      y = [1,2,3,4]
      
      spam = [[s,t] for s in x for t in y]
      
      for x in spam:
          print('%s - %s' %(x[0], x[1]))
      

      输出:

      1 - 1
      1 - 2
      1 - 3
      1 - 4
      2 - 1
      2 - 2
      2 - 3
      2 - 4
      3 - 1
      3 - 2
      3 - 3
      3 - 4
      4 - 1
      4 - 2
      4 - 3
      4 - 4
      

      【讨论】:

        猜你喜欢
        • 2010-11-25
        • 1970-01-01
        • 1970-01-01
        • 2014-10-16
        • 2017-09-21
        • 2012-08-10
        • 2019-08-24
        • 2023-03-17
        相关资源
        最近更新 更多