web-dev-qa-db-ja.com

反復中のリストの変更

l  = range(100)                         
for i in l:                         
    print i,                         
    print l.pop(0),                  
    print l.pop(0)

上記のpythonコードは、予想とはまったく異なる出力を提供します。ループ中にアイテムをスキップできるように、アイテムをループします。

説明してください。

50
Xolve

リストを繰り返し処理しながらリストを変更しようとする(他の誰かの)「巧妙な」コードに噛まれたことがあります。どんな状況でも絶対にやらないと決心しました。

スライス演算子mylist[::3]を使用して、リスト内の3番目のアイテムごとにスキップできます。

mylist = [i for i in range(100)]
for i in mylist[::3]:
  print(i),

私の例に関する他のポイントは、 python 3. の新しい構文に関連しています。

  • Python 3.0(以下を参照)で動作するため、リストの内包表記を使用してmylistを定義します
  • printはpython 3.0の関数です

Python 3.0のrange()は、任意のサイズの値で動作することを除いて、動作するために使用されるxrange()のように動作するようになりました。後者はもう存在しません。

40
Ewan Todd

ループしているコンテナを変更しないでください。そのコンテナのイテレータには変更が通知されないため、お気付きのとおり、非常に異なるループや不正なループが生成される可能性が高いからです。通常の場合、コンテナのコピーでループするのが役立ちますが、あなたの場合、コンテナがループの50レッグ後に空になるので、あなたがdo n'tしたいことは明らかですもう一度ポップしてみると、例外が発生します。

しかし、明確なことは何ですか、もしあれば、あなたはどのような行動を達成しようとしていますか?!たぶん、あなたはwhile...であなたの欲望を表現できますか?

i = 0
while i < len(some_list):
    print i,                         
    print some_list.pop(0),                  
    print some_list.pop(0)
50
Alex Martelli

一般的な経験則として、コレクション/配列/リストを繰り返し処理している間は変更しないでください。

セカンダリリストを使用して、操作対象のアイテムを保存し、最初のループの後にそのロジックをループで実行します。

11
Paul Sasik

これを試して。繰り返し処理しているもの(通常はコードの匂い)を変更しないようにします。

for i in xrange(0, 100, 3):
    print i

xrange を参照してください。

8
Hank Gay

配列の真実性をチェックするwhileループを使用します。

while array:
    value = array.pop(0)
    # do some calculation here

そして、エラーやおかしな振る舞いなしにそれを行うべきです。

8
Eugene Eeo

私はこれがあなたが望むものだと思う:

l  = range(100)  
index = 0                       
for i in l:                         
    print i,              
    try:
        print l.pop(index+1),                  
        print l.pop(index+1)
    except:
        pass
    index += 1

ポップするアイテムの数が実行時の決定である場合、コーディングすることは非常に便利です。しかし、それは非常に悪い効率で実行され、コードを維持するのは難しいです。

1
York Chang

このスライス構文はリストのコピーを作成し、あなたが望むことをします:

l  = range(100)  
for i in l[:]:  
    print i,  
    print l.pop(0),  
    print l.pop(0)
0
thethinman