2009-10-13 23 views
13

私はジェネレータオブジェクトを逆にする方法を探しています。私は順序を逆にする方法を知っている:Python Reverse Generator

foo = imap(seq.__getitem__, xrange(len(seq)-1, -1, -1)) 

しかし、出力として入力し、逆発電機(LEN(配列)は同じままなので、元のシーケンスから値を得るように発電機を持つことができ似たようです中古)?

+3

シーケンスを逆転させる例は例外です。なぜ、「逆転」を使用しないのですか?または '.reverse'?あなたが書いたものよりも 'seq [:: - 1]'ははっきりしています。 –

+0

これらの例はすべて新しいリストを作成するためです。上記の私の例は、リストを最初にコピーせずに作成する唯一の方法です。 –

+0

まあ、私は新しいことを学びました - seq [:: - 1] *は実際には新しいリストを作成します。負のインデックスを使用する代わりに、私のジェネレータ表現の答えを見てください。 – PaulMcG

答えて

19

ジェネレータをシーケンスにキャストし、ジェネレータからイテレータを作成する以外はジェネリックな方法でジェネレータを元に戻すことはできません。発電機の後の項は、以前のものが計算されるまで必ずしも分かるとは限らない。

さらに悪いことに、ヒットするまでジェネレータがStopIteration例外を突き止めるかどうかを知ることができないため、シーケンスの最初の用語が何であるかを知る方法がありません。

あなたができる最善のはreversed_iterator関数を記述するために、次のようになります。

def reversed_iterator(iter): 
    return reversed(list(iter)) 

EDIT:あなたはまた、当然のことながら、1つのリストの作成を節約するために、あなたのIMAPベースの反復バージョンでこれを逆に置き換えることができます。

+13

厳密に言えば、 'list(iter)'は* cast *ではありません。iterator iterを消費してリストを構築します。私はPythonが* cast *関数を持っているかどうかはわかりません。少なくともCやJavaのような言語で使われるという意味ではありません。 int( "100")はキャストではなく、float(100)はキャストではありません。どちらもオブジェクトを返すコンストラクタです。 Cでは、何かがキャストされると、元のオブジェクトは同じままです。 Pythonでこのようなことをした場合、元の値のidとキャストされた値を取ることができ、それらは同じになります。要するに、Pythonでは、キャストが死んでいます。 – PaulMcG

+5

「キャストが死んでしまった」:良いもの! :) –

+2

@Paul McGuire:あなたが言った重要な部分に同意します。しかし、Cではキャスト*は元のオブジェクトを変更することができます。 100をfloatにキャストすると、Cはそれを100.0fに変更します。 Cはfloat変数にビットパターン0x00000064を投げるだけではなく、浮動小数点数になる値に変換します。Cでは、キャストは単純に型を変更することができます( 'int *'を 'long int *'に変更する、 'int'を' long int'に変更する)か、値と型を変更することができます。 C++には、値をまったく変更せずに型を再解釈するものを含む、いくつかのキャスト演算子があります。 – steveha

6

reversed(list(input_generator))おそらく最も簡単な方法です。

ジェネレータの値を最初に生成したので、2番目のアイテムを生成することが非常にうまくいくため、ジェネレータの値をシーケンスに最初に集めることなく、逆の順序で取得する方法はありません。

4

リストを作成するには、最初の項目を取得するためにジェネレータを通過する必要があります。試してみてください

reversed(list(g)) 

ここで、gはジェネレータです。

reversed(tuple(g)) 

(パフォーマンスに大きな違いがあるかどうかは確認していません)。