迭代Python中的多个起止值

时间:2019-12-13 18:12:07

标签: python

假设我有一个数字l,我想将其分成大致相等的n块。例如:

l = 11
n = 3
step = 1 + l // n

for start in range(0, l, step):
    stop = min(l, start+step)
    print(start, stop)

在这种情况下,第一个块(块0)从0到4(5个元素),下一个块(块1)从4到8(5个元素),并且最后一块(块2)稍小,从8到11(4个元素)。当然,ln的值可以变化,但是两个值将始终为正整数,并且n始终小于l

我需要做的是生成一个列表,该列表将以循环方式遍历每个块,并将一些块信息附加到列表中。该列表应包含一个块编号(即012)的元组和该块中的下一个可用的起始值(直到该块由stop值)。因此,输出列表将是:

[(0,0), (1,4), (2,8), (0,1), (1,5), (2,9), (0,2), (1,6), (2,10), (0,3), (1,7)]

请注意,最后一个块比前两个块具有最后一个元素。无论解决方案是什么,它都需要适用于任何ln(只要两个值都是正整数,并且n始终小于l)。为简单起见,您可以假设l小于100,000,000。

生成此列表的最佳方法是什么?

2 个答案:

答案 0 :(得分:1)

对问题的两个级别使用两个循环。外循环通过range(step)中的所有数字作为起点。从那里开始,使用该值作为您已经编写的内部循环的起点。请注意,您必须调整输出:当请求的输出具有(块号,开始)值时,您正在打印(开始,停止)值。

你能从那里拿走吗?

答案 1 :(得分:0)

使用生成器的一种可能的解决方案:

from itertools import islice, zip_longest, cycle

def chunk(it, size):
    it = iter(it)
    return iter(lambda: tuple(islice(it, size)), ())

def generate(l, n):
    c, step = cycle(range(n)), l // n + (l % n != 0)
    yield from ((next(c), v) for vals in zip_longest(*chunk(range(l), step)) for v in vals if v is not None)

l = 11
n = 3

out = [*generate(l, n)]
print(out)

打印:

[(0, 0), (1, 4), (2, 8), (0, 1), (1, 5), (2, 9), (0, 2), (1, 6), (2, 10), (0, 3), (1, 7)]

针对:

l = 9
n = 3

输出为:

[(0, 0), (1, 3), (2, 6), (0, 1), (1, 4), (2, 7), (0, 2), (1, 5), (2, 8)]