在python中生成具有给定边界的范围元组列表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14048728/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Generate list of range tuples with given boundaries in python
提问by favoretti
[edit] I'm not sure if this better off to codereview, if so, please migrate :) thanks!
[编辑] 我不确定这对代码是否更好,如果是这样,请迁移 :) 谢谢!
So we were sitting here, working on a semi-academic problem.
所以我们坐在这里,研究一个半学术问题。
Given a start, stopand step, generate a list of range tuples, so that
给定 a start, stopand step,生成一个范围元组列表,使得
gen_range(100, 140, 10)
would produce
会产生
[(100, 110), (110, 120), (120, 130), (130, 140)]
also, given then fact that it should work on, say, iterating 500M integers with a step of 100 and not take forever.
此外,考虑到它应该以 100 的步长迭代 500M 整数而不是永远的事实。
The implementation I've come up with is as follows:
我提出的实现如下:
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)
But I can't stop thinking that it can be done in a more efficient (also code-length wise) way. Any suggestions?
但我不能停止认为它可以以更有效(也是代码长度明智)的方式完成。有什么建议?
[edit]
[编辑]
One thing I forgot to point out. If the range boundary is not equal to the step, i.e. you have a case of:
我忘了指出一件事。如果范围边界不等于步长,即您有以下情况:
gen_range(100, 143, 10)
the upper boundary should be 143, and not 150, as some answers here would produce, due to range()internals.
由于range()内部原因,上限应该是 143,而不是 150,因为这里的一些答案会产生。
采纳答案by Amber
A really short way:
一个非常简短的方法:
ranges = [(n, min(n+step, stop)) for n in xrange(start, stop, step)]
More verbose ways:
更详细的方法:
Perhaps via a generator?
也许通过发电机?
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
Calling this function gives you a generator object that will produce each of the tuples in order. You would use it like this:
调用此函数将为您提供一个生成器对象,它将按顺序生成每个元组。你会像这样使用它:
for block in gen_range(100000000,600000000,100):
print block
which would output...
这将输出...
(100000000,100000100)
(100000100,100000200)
(100000200,100000300)
...
(599999900,600000000)
You could do this even more simply with a generator expression if you're always certain that stop-startis an even multiple of the step:
如果您始终确定它stop-start是 的偶数倍,则可以使用生成器表达式更简单地执行此操作step:
ranges = ((n, n+step) for n in xrange(start, stop, step))
# Usage
for block in ranges:
print block
Also note that if you want to turn a generator into a list, holding the entirety of the results in memory, you can simply pass it to list():
另请注意,如果要将生成器转换为列表,将所有结果保存在内存中,只需将其传递给list():
all_ranges = list(gen_range(100000000,600000000,100))
回答by Ashwini Chaudhary
something like this:
像这样:
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)]
or using zip():
或使用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)]
回答by irrelephant
Maybe code-length wise if (b - a) % c == 0:
也许代码长度明智,如果(b - a) % c == 0:
def gen_range(a, b, c):
return [(i, i + c) for i in range(a, b, c)]
or
或者
def gen_range_2(a, b, c):
s = range(a, b + c, c)
return zip(s, s[1:])
If (b - a) % c != 0:
如果(b - a) % c != 0:
def gen_range(a, b, c):
return [(i, i + c) for i in range(a, b - ((b - a) % c), c)]
or
或者
def gen_range_2(a, b, c):
s = range(a, b - ((b - a) % c) + c, c)
return zip(s, s[1:])
回答by EnricoGiampieri
I'm not sure if I correctly understood the problem, but this can be simply done with a list comprehension:
我不确定我是否正确理解了这个问题,但这可以通过列表理解来简单地完成:
start = 100
stop = 140
step = 10
[ range(s,s+step+1,step) for s in range(start,stop,step)]
if you need only to iterate over your list element one at the time, I strongly suggest you to use a generator comprehension instead:
如果您当时只需要迭代您的列表元素之一,我强烈建议您改用生成器理解:
res = ( range(s,s+step+1,step) for s in range(start,stop,step))
You can iterate over it in a cycle:
您可以循环遍历它:
for range_piece in res:
do_something with it
回答by martineau
I'd make it a generator so it could handle huge ranges.
我会把它做成一个发电机,这样它就可以处理很大的范围。
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))
回答by tanantish
I'd go with the generator approach, but if you're going to be unpacking the thing into an explicit list, another way to look at it is that you've got a really simple relationship between the elements of your tuple, and all you need to do is range the length properly.
我会使用生成器方法,但是如果您要将事物解包到一个显式列表中,另一种看待它的方式是您的元组元素与所有元素之间有一个非常简单的关系你需要做的是适当地调整长度。
def gen_range(start, stop, step):
items = ((stop-start) // step)
return [(start+(n*step), start+(n+1)*step) for n in range(items)]
The onlyreason I figured it's worth posting this is that my first thought (and hence the comment query) whether or not you could get away with just asking for the nth tuple in the list without having to generate the lot. If you can't, then I wouldn't go down this angle.
我认为值得发布的唯一原因是我的第一个想法(以及评论查询)您是否可以只要求列表中的第 n 个元组而不必生成很多。如果你不能,那么我不会走下这个角度。
回答by Bin Chen
I think generator is a good try:
我认为发电机是一个很好的尝试:
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)]

