Python -- 迭代一个迭代器两次
Python -- Iterate an iterator twice
编辑:有一个 similar question here 处理迭代器重置。然而,下面接受的答案解决了嵌套迭代器的实际问题,并处理了一个容易遗漏的问题,即嵌套迭代器不会重置。
有什么方法可以在 python 中对迭代器进行两次迭代?
在下面的示例代码中,我可以看到第二次迭代与第一次迭代在同一个对象上运行,因此产生了一个奇怪的结果。将此与下面的 C# 进行对比,生成我想要的结果。
有什么方法可以做我想做的。我想知道我是否可以复制迭代器或 "retrieve" 它来自的函数,但也许有更简单的方法。 (我知道我可以在下面的玩具示例中调用 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
. . .
您可以使用 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
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());
编辑:有一个 similar question here 处理迭代器重置。然而,下面接受的答案解决了嵌套迭代器的实际问题,并处理了一个容易遗漏的问题,即嵌套迭代器不会重置。
有什么方法可以在 python 中对迭代器进行两次迭代?
在下面的示例代码中,我可以看到第二次迭代与第一次迭代在同一个对象上运行,因此产生了一个奇怪的结果。将此与下面的 C# 进行对比,生成我想要的结果。
有什么方法可以做我想做的。我想知道我是否可以复制迭代器或 "retrieve" 它来自的函数,但也许有更简单的方法。 (我知道我可以在下面的玩具示例中调用 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
. . .
您可以使用 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
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());