81

範囲関数は連結を許可しますか? 私が作りたいようにrange(30)& と連結しrange(2000, 5002)ます。だから私の連結範囲は0, 1, 2, ... 29, 2000, 2001, ... 5001

このようなコードは、最新の python (ver: 3.3.0) では機能しません。

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

8 に答える 8

86

これに使用できますitertools.chain

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

任意のイテラブルに対して機能します。range()Python 2 と 3 では、知っておくべきの動作の違いがあることに注意してください。Python 2rangeではリストを返し、Python3 ではイテレータを返します。これはメモリ効率が高いですが、常に望ましいとは限りません。

リストは で連結できますが+、イテレータは連結できません。

于 2012-12-31T09:36:22.427 に答える
49

私は可能な限り最も単純なソリューションが好きです (効率を含む)。解決策がそのようなものであるかどうかは、必ずしも明確ではありません。とにかく、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倍高速です。

于 2012-12-31T12:40:38.527 に答える
37

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
于 2012-12-31T09:52:18.210 に答える
9

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]
于 2012-12-31T12:55:52.553 に答える
4

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()したがって、他の人が指摘したように、他のイテレータを連結できないことは明らかです。

于 2012-12-31T09:43:10.713 に答える
0

この質問にたどり着いたのは、重複する可能性のある不明な数の範囲を連結しようとしていて、最終イテレータで値を繰り返す必要がなかったからです。私の解決策は、次のような演算子を使用することでしsetunion

range1 = range(1,4)
range2 = range(2,6)
concatenated = set.union(set(range1), set(range2)
for i in concatenated:
    print(i)
于 2016-10-28T21:58:18.790 に答える