範囲関数は連結を許可しますか? 私が作りたいようにrange(30)
& と連結しrange(2000, 5002)
ます。だから私の連結範囲は0, 1, 2, ... 29, 2000, 2001, ... 5001
このようなコードは、最新の python (ver: 3.3.0) では機能しません。
range(30) + range(2000, 5002)
範囲関数は連結を許可しますか? 私が作りたいようにrange(30)
& と連結しrange(2000, 5002)
ます。だから私の連結範囲は0, 1, 2, ... 29, 2000, 2001, ... 5001
このようなコードは、最新の python (ver: 3.3.0) では機能しません。
range(30) + range(2000, 5002)
これに使用できますitertools.chain
:
from itertools import chain
concatenated = chain(range(30), range(2000, 5002))
for i in concatenated:
...
任意のイテラブルに対して機能します。range()
Python 2 と 3 では、知っておくべきの動作の違いがあることに注意してください。Python 2range
ではリストを返し、Python3 ではイテレータを返します。これはメモリ効率が高いですが、常に望ましいとは限りません。
リストは で連結できますが+
、イテレータは連結できません。
私は可能な限り最も単純なソリューションが好きです (効率を含む)。解決策がそのようなものであるかどうかは、必ずしも明確ではありません。とにかく、range()
Python 3 の はジェネレーターです。反復を行う任意の構造にラップできます。はlist()
、任意の iterable からリスト値を構築できます。リストの+
演算子は連結を行います。この例では、より小さい値を使用しています。
>>> 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 では、本当にリストを作成したい場合にのみ役に立ちます。それ以外の場合は、 itertools.chain を使用したLev Levitskyのソリューションをお勧めします。ドキュメントには、非常に簡単な実装も示されています。
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 と、標準ライブラリの使用に関する彼の議論に行きます。The Zen of 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倍高速です。
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]
あなたのリクエストには応えますが、長い回答なのでここには投稿しません。
注:パフォーマンスを向上させるためにジェネレーターにすることができます:
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
extendメソッドを使用すると、2つのリストを連結できます。
>>> 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]
range()
Python 2.x ではリストを返します:
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
xrange()
Python 2.x では、イテレータを返します。
>>> xrange(10)
xrange(10)
Python 3 ではrange()
、イテレータも返します。
>>> r = range(10)
>>> iterator = r.__iter__()
>>> iterator.__next__()
0
>>> iterator.__next__()
1
>>> iterator.__next__()
2
chain()
したがって、他の人が指摘したように、他のイテレータを連結できないことは明らかです。
この質問にたどり着いたのは、重複する可能性のある不明な数の範囲を連結しようとしていて、最終イテレータで値を繰り返す必要がなかったからです。私の解決策は、次のような演算子を使用することでしset
たunion
:
range1 = range(1,4)
range2 = range(2,6)
concatenated = set.union(set(range1), set(range2)
for i in concatenated:
print(i)