[编辑]我不确定这对codereview是否更好,如果是,请迁移:)谢谢!
所以我们坐在这里,研究半学术问题。
给定start
,stop
和step
,生成范围元组列表,以便
gen_range(100, 140, 10)
会产生
[(100, 110), (110, 120), (120, 130), (130, 140)]
同样,如果事实它应该工作,比如说,迭代500M整数,步长为100而不是永远。
我提出的实施如下:
def gen_range(start, stop, step):
llist = range(start, stop+step, step)
batch_list = []
if llist[-1] > stop:
llist[-1] = stop
for a, b in enumerate(llist[:-1]):
batch_list.append((llist[a], llist[a+1]))
print batch_list
gen_range(100000000,600000000,100)
但我不能不认为它可以以更有效(也是代码长度方式)的方式完成。有什么建议吗?
[编辑]
有一件事我忘了指出。如果范围边界不等于该步骤,即您有以下情况:
gen_range(100, 143, 10)
由于range()
内部原因,上边界应为143,而不是150,因为这里的一些答案会产生。
答案 0 :(得分:5)
ranges = [(n, min(n+step, stop)) for n in xrange(start, stop, step)]
也许是通过发电机?
def gen_range(start, stop, step):
current = start
while current < stop:
next_current = current + step
if next_current < stop:
yield (current, next_current)
else:
yield (current, stop)
current = next_current
调用此函数会为您提供一个生成器对象,该对象将按顺序生成每个元组。你可以这样使用它:
for block in gen_range(100000000,600000000,100):
print block
将输出......
(100000000,100000100)
(100000100,100000200)
(100000200,100000300)
...
(599999900,600000000)
如果您始终确定stop-start
是step
的偶数倍,则可以使用生成器表达式更简单地执行此操作:
ranges = ((n, n+step) for n in xrange(start, stop, step))
# Usage
for block in ranges:
print block
另请注意,如果您想将生成器转换为列表,将整个结果保存在内存中,您只需将其传递给list()
:
all_ranges = list(gen_range(100000000,600000000,100))
答案 1 :(得分:1)
我不确定我是否正确理解了这个问题,但这可以通过列表理解来完成:
start = 100
stop = 140
step = 10
[ range(s,s+step+1,step) for s in range(start,stop,step)]
如果您当时只需要迭代列表元素,我强烈建议您改为使用生成器理解:
res = ( range(s,s+step+1,step) for s in range(start,stop,step))
您可以循环迭代它:
for range_piece in res:
do_something with it
答案 2 :(得分:0)
类似的东西:
In [48]: it=iter(xrange(100,200,10))
In [49]: it1=iter(xrange(110,210,10))
In [50]: [(next(it),next(it1)) for _ in range(10)]
Out[50]:
[(100, 110),
(110, 120),
(120, 130),
(130, 140),
(140, 150),
(150, 160),
(160, 170),
(170, 180),
(180, 190),
(190, 200)]
或使用zip()
:
In [55]: it=iter(xrange(100,200,10))
In [56]: it1=iter(xrange(110,210,10))
In [57]: [(x,y) for x,y in zip(it,it1)]
Out[57]:
[(100, 110),
(110, 120),
(120, 130),
(130, 140),
(140, 150),
(150, 160),
(160, 170),
(170, 180),
(180, 190),
(190, 200)]
答案 3 :(得分:0)
如果(b - a) % c == 0
:
def gen_range(a, b, c):
return [(i, i + c) for i in range(a, b, c)]
或
def gen_range_2(a, b, c):
s = range(a, b + c, c)
return zip(s, s[1:])
如果(b - a) % c != 0
:
def gen_range(a, b, c):
return [(i, i + c) for i in range(a, b - ((b - a) % c), c)]
或
def gen_range_2(a, b, c):
s = range(a, b - ((b - a) % c) + c, c)
return zip(s, s[1:])
答案 4 :(得分:0)
我会让它成为一个发电机,因此它可以处理大范围。
def gen_range(start, stop, step):
a, b = start, start+step
while b <= stop:
yield a, b
a, b = b, b+step
print list(gen_range(100, 140, 10))
答案 5 :(得分:0)
我会使用生成器方法,但是如果你要将这个东西拆包到一个明确的列表中,另一种看待它的方法是你的元组元素之间有一个非常简单的关系,你需要做的就是适当地调整长度。
def gen_range(start, stop, step):
items = ((stop-start) // step)
return [(start+(n*step), start+(n+1)*step) for n in range(items)]
唯一的原因我认为值得发布这是我的第一个想法(因此评论查询)你是否可以逃避只是在列表中要求第n个元组而没有生成这个地段。如果你做不到,那么我就不会这么做了。
答案 6 :(得分:0)
我认为发电机是一个很好的尝试:
def gen_range(start, stop, step):
while start < stop:
yield (start, min(start + step, stop))
start = start + step
if __name__ == '__main__':
print [x for x in gen_range(100, 143, 10)]