多次迭代的循环?

时间:2010-09-23 02:26:29

标签: python

假设:

x = ['a','b','c','d','e']
y = ['1','2','3']

我想迭代导致:

a, 1
b, 2
c, 3
d, 1
e, 2
a, 3
b, 1

...两个iterables独立循环直到给定的计数。

Python的循环(可迭代)可以做到这一点w / 1 iterable。 map和itertools.izip_longest等函数可以使用函数来处理None,但不提供内置的自动重复。

一个不那么狡猾的想法是将每个列表连接到一定的大小,我可以从中均匀地迭代。 (Boooo!)

连连呢?提前谢谢。

2 个答案:

答案 0 :(得分:10)

最简单的方法是在cyclezip1下方。它对于大多数用途来说足够快。

import itertools

def cyclezip1(it1, it2, count):
    pairs = itertools.izip(itertools.cycle(iter1),
                           itertools.cycle(iter2))
    return itertools.islice(pairs, 0, count)

以下是它的另一种实现,当count明显大于it1it2的最小公倍数时,其速度大约是其两倍。

import fractions

def cyclezip2(co1, co2, count):
    l1 = len(co1)
    l2 = len(co2)
    lcm = l1 * l2 / float(fractions.gcd(l1, l2))
    pairs = itertools.izip(itertools.cycle(co1),
                           itertools.cycle(co2))
    pairs = itertools.islice(pairs, 0, lcm)
    pairs = itertools.cycle(pairs)
    return itertools.islice(pairs, 0, count)

这里我们利用了这样一个事实:成对将在n的{​​{1}}之后循环,其中nlen(it1)len(it2)的最不常见的多个部分。这当然假设迭代是集合,因此询问它们的长度是有意义的。可以进行的进一步优化是 替换

pairs = itertools.islice(pairs, 0, lcm)

pairs = list(itertools.islice(pairs, 0, lcm))

这并不是一种改进(在我的测试中约为2%)并且几乎不一致。它还需要更多的内存。如果提前知道it1it2足够小,以便额外的内存可以忽略不计,那么你可以从中挤出额外的性能。

值得注意的是,在集合的情况下,显而易见的事情比第一个选项慢了四倍。

def cyclezip3(co1, co2, count):
    l1 = len(co1)
    l2 = len(co2)
    return ((co1[i%l1], co2[i%l2]) for i in xrange(count))

答案 1 :(得分:7)

import itertools
x = ['a','b','c','d','e']
y = ['1','2','3']
for a, b in itertools.izip(itertools.cycle(x), itertools.cycle(y)):
    print a, b