簡體   English   中英

在python中生成具有給定邊界的范圍元組列表

[英]Generate list of range tuples with given boundaries in python

[編輯]我不確定這是否更好的代碼審查,如果是這樣,請遷移:)謝謝!

所以我們坐在這里,研究半學術問題。

給定一個startstopstep ,生成一個范圍元組列表,這樣

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,因為這里的一些答案會產生。

一個很短的方式:

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-startstep的偶數倍,則可以使用生成器表達式更簡單地執行此操作:

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))

我不確定我是否正確理解了這個問題,但這可以通過列表理解來完成:

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

這樣的事情:

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)]

如果(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:])

http://ideone.com/VhY215

如果(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:])

http://ideone.com/i3Pq69

我會把它變成一台發電機,因此可以處理大范圍。

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))

我會選擇生成器方法,但是如果你打算將這個東西解壓縮到一個明確的列表中,另一種看待它的方法就是你的元組元素和所有元素之間的關系非常簡單你需要做的是適當地調整長度。

def gen_range(start, stop, step):
   items = ((stop-start) // step)
   return [(start+(n*step), start+(n+1)*step) for n in range(items)]

我認為值得發布這個的唯一原因是我的第一個想法(以及評論查詢)是否可以逃避只需要在列表中詢問第n個元組而不必生成批次。 如果你不能,那么我就不會走這個角度了。

我認為發電機是一個很好的嘗試:

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)]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM