Python——迭代一个迭代器两次

Python——迭代一个迭代器两次,python,for-loop,iterator,generator,yield,Python,For Loop,Iterator,Generator,Yield,编辑:有一个函数处理迭代器重置。然而,下面接受的答案解决了嵌套迭代器的实际问题,并处理了一个容易忽略的问题,即嵌套迭代器不会重置 在python中有没有任何方法可以在迭代器上迭代两次 在下面的示例代码中,我可以看到第二次迭代与第一次迭代在同一个对象上运行,因此产生了一个奇怪的结果。将此与下面的C#进行对比,得出我想要的结果 有没有办法做我想做的事。我想知道是否可以复制迭代器或“检索”它来自的函数,但也许有一种更简单的方法。(我知道我可以在下面的玩具示例中调用两次MyIter(),但如果我不知道迭

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

在python中有没有任何方法可以在迭代器上迭代两次

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

有没有办法做我想做的事。我想知道是否可以复制迭代器或“检索”它来自的函数,但也许有一种更简单的方法。(我知道我可以在下面的玩具示例中调用两次
MyIter()
,但如果我不知道迭代器来自何处,也不知道我要的不是迭代器,那就没用了!)

给予

与之相比:

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
. . .

您可以使用
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())

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

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
从单个iterable创建独立迭代器。但是,一旦创建了新的iterable,就不应该再使用原来的iterable了

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());

您可以在python中无限次地迭代迭代器。但是,如果您引用的是生成器(从给定代码的外观来看,您就是这样),那么在生成器本身上无法多次这样做。不过,您可以将生成器结果保存在内存中,并对其进行迭代。在您给出的示例中,您可以通过调用
PrintCombos(list(MyIter()))
来实现这一点。您可能需要的是
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
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());