2012-12-31 109 views
33

範圍函數是否允許連接?就像我想做一個range(30) &連接它與range(2000, 5002)。所以,我的級聯範圍將是0, 1, 2, ... 29, 2000, 2001, ... 5001連接兩個範圍函數結果

這樣的代碼不會對我的最新的Python工作(版本:3.3.0)

range(30) + range(2000, 5002) 
+0

python version? –

+0

我的python版本是3.3.0版本..我也更新了我的問題 – MAG

+1

你想得到什麼結果(如在什麼類型的數據 - 一個簡單的列表,一個生成器,其他的東西)?你想對結果做什麼? –

回答

34

您可以使用itertools.chain此:

from itertools import chain 
concatenated = chain(range(30), range(2000, 5002)) 
for i in concatenated: 
    ... 

它適用於任意迭代。請注意,您應該瞭解Python 2和Python 3之間的range()的行爲差異:在Python 2中,range返回一個列表,在Python3中返回一個迭代器,這是一種內存有效的,但並不總是可取的。

列表可以連接+,迭代器不能。

3

在Python 2.x的range()返回一個列表:

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

在Python 2.x的xrange()返回迭代:

>>> xrange(10) 
xrange(10) 

而且在Python 3 range()也返回一個迭代:

>>> r = range(10) 
>>> iterator = r.__iter__() 
>>> iterator.__next__() 
0 
>>> iterator.__next__() 
1 
>>> iterator.__next__() 
2 

所以很明顯,你不能其他人通過使用chain()連接迭代器。

+1

您的回答很有幫助,但不提供解決方案。 –

23

可以使用list-comprehension來完成。

>>> [i for j in (range(10), range(15, 20)) for i in j] 
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 16, 17, 18, 19] 

Works爲您的要求,但它是一個長期的答案,所以我不會在這裏發佈。

注:可製成用於提高性能發電機:

for x in (i for j in (range(30), range(2000, 5002)) for i in j): 
    # code 

,甚至到發電機變量。

gen = (i for j in (range(30), range(2000, 5002)) for i in j) 
for x in gen: 
    # code 
+3

+1沒有額外的依賴關係 – mkind

+0

@mkind謝謝,我討厭依賴關係,人們總是跳躍和回答大量的進口和庫,但它們並不總是可用的,而且他們經常做與普通代碼一樣的事情,只是包裝在一個包裏,它不是魔術。 :) –

+7

我不認爲_not使用標準庫_本身就是一種優點,但這是一個很好的答案。 –

17

我喜歡可能的最簡單的解決方案(包括效率)。解決方案是否如此並不總是很清楚。無論如何,Python 3中的range()是一個生成器。你可以把它包裝到任何迭代的結構中。 list()能夠從任何迭代中構建列表值。用於列表的+運算符不會串聯。我在例如使用更小的值:

>>> list(range(5)) 
[0, 1, 2, 3, 4] 
>>> list(range(10, 20)) 
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19] 
>>> list(range(5)) + list(range(10,20)) 
[0, 1, 2, 3, 4, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] 

這是range(5) + range(10, 20)在Python 2.5究竟做了 - 因爲range()返回一個列表。

在Python 3中,它只有在你真的想構造列表時纔有用。否則,我建議Lev Levitsky's解決方案與itertools.chain。該文檔還顯示了非常簡單的實現:

def chain(*iterables): 
    # chain('ABC', 'DEF') --> A B C D E F 
    for it in iterables: 
     for element in it: 
      yield element 

該解決方案通過Inbar Rose是精細和功能上等同。無論如何,我的+1會轉到Lev Levitsky和他有關使用標準庫的爭論。從的Python的禪...

在不確定性面前,拒絕誘惑猜測。

#!python3 
import timeit 
number = 10000 

t = timeit.timeit('''\ 
for i in itertools.chain(range(30), range(2000, 5002)): 
    pass 
''', 
'import itertools', number=number) 
print('itertools:', t/number * 1000000, 'microsec/one execution') 

t = timeit.timeit('''\ 
for x in (i for j in (range(30), range(2000, 5002)) for i in j): 
    pass 
''', number=number) 
print('generator expression:', t/number * 1000000, 'microsec/one execution') 

在我看來,該itertools.chain是更具可讀性。但真正重要的是......

itertools: 264.4522138986938 microsec/one execution 
generator expression: 785.3081048010291 microsec/one execution 

......它快了大約3倍。

+0

這很好,我會承認有效構建標準庫模塊會失敗。但是你的時機很奇怪,經過多次測試後,我發現我的解決方案只有1.8倍的速度,而慢了3倍。但它仍然較慢。 –

+0

它絕對依賴於硬件,可能也取決於操作系統。我確實使用了我的相當過時的計算機,它配備了2.01 GHz的AMD Athlon 64 X2雙核處理器3800+,以及3 GB的內存。操作系統是Windows 7家庭高級版64位(處理器和內存分數都只有4,9 - http://windows.microsoft.com/en-US/windows7/What-is-the-Windows-Experience-Index) 。我不確定Python的實現。假設你可能有更多的處理器內核。 – pepr

2

藉助於extend方法,我們可以連接兩個列表。

>>> a = list(range(1,10)) 
>>> a.extend(range(100,105)) 
>>> a 
[1, 2, 3, 4, 5, 6, 7, 8, 9, 100, 101, 102, 103, 104] 
+2

這是針對Python 2,OP使用Python 3. –

+1

Extend不是關鍵字,它是Python列表中的一種方法。 – user7610

1

我來到了這個問題,因爲我試圖來連接數目不詳的範圍,可能會重疊,不希望在最後的迭代重複的值。我的解決方案是使用setunion這樣的運營商:

range1 = range(1,4) 
range2 = range(2,6) 
concatenated = set.union(set(range1), set(range2) 
for i in concatenated: 
    print(i)