2009-04-12 12 views
8

私は現在Pythonでプログラムを開発していますが、言語のforeachループやリスト構造に何か問題があったことに気付きました。forループまたはリストのPythonの奇妙な動作

x = [1,2,2,2,2] 

for i in x: 
    x.remove(i) 

print x   

さてここで問題は、私もこのコードという、単純である、:私は私のプログラムと私の一般的な例の両方で同じ誤った動作を得るため、私は、簡単にするために私の問題の一般的な例をあげますリストからすべての要素を削除することになっていました。まあ、問題は、実行後、私は常に2つの残りの要素をリストに入れます。

私は間違っていますか?すべての助けを前もってありがとう。

編集:私は、これは一例であり、リストを空にしたくない...

+0

あなたが経験する問題には以下の解決策がありますが、「x = []」に短縮する必要があるとは思えません。問題の原因となっている実際のコードを投稿するともっと面白いかもしれませんか? – gnud

+0

本当の問題を投稿する必要があります。 list.removeは、リストを検索してから、削除されたonに続くすべての要素を前方にシフトする必要があるため、かなり非効率的です。 – Miles

答えて

30

これは、あなたが反復されてリストを変更することになっていないことを、Pythonで十分に文書化された動作ですスルー。代わりにこれを試してみてください:

for i in x[:]: 
    x.remove(i) 

[:]は、そのすべての要素が含まれているために起こるxの「スライス」を返し、かつ効果的にこれxのコピーです。

+0

参照:http://docs.python.org/tutorial/controlflow.html#for-statements –

+0

ありがとうございました:) – rogeriopvl

+0

これは、rogeriopvlの質問にリストに2つの要素が含まれている理由を説明していません。この説明が真であれば、リストは無傷であるべきです。 –

11

要素を削除し、for-loop incsを次のインデックスに追加すると、要素をスキップします。

それを逆にします。または、あなたの本当の問題を述べてください。

あなただけ使用していないのはなぜ
3

x = [] 

あなたは反復処理している同じ配列を変更しているので、それはおそらくです。

あなたの方法でアレイをクリアしたい場合は、Chris-Jester Youngの答えをお試しください。あなたはループ本体のためのlst.remove(x)を挿入した場合、おそらく、

i = 0 
while i < len(lst): 
    x = lst[i] 
    # loop body goes here 
    i += 1 

:私は思う

4

は、広くあなたが書いたときにことを、話す:

for x in lst: 
    # loop body goes here 

ボンネットの下に、Pythonはこのような何かをやっていますあなたは結果を得る理由を知ることができます。

本質的に、pythonは移動ポインタを使用してリストを走査します。ポインタは、最初の要素を指すことによって開始します。次に、最初の要素を削除して、第2の要素を新しい最初の要素にします。その後、ポインタは新しい2番目の以前の3番目の要素に移動します。等々。 (サンプルリストとして[1,2,2,2,2]の代わりに[1,2,3,4,5]を使用すると、より明確になる可能性があります)

1

私は、John Fouhyとブレーク条件。 Chris Jester-Youngが提案しているように、リストのコピーをトラバースすることはremove()メソッドで機能します。しかし、Erikが述べたように、特定のアイテムをポップする必要がある場合は逆の作業を繰り返します。この場合、操作はその場で実行できます。たとえば、次のように

def r_enumerate(iterable): 
    """enumerator for reverse iteration of an iterable""" 
    enum = enumerate(reversed(iterable)) 
    last = len(iterable)-1 
    return ((last - i, x) for i,x in enum) 

x = [1,2,3,4,5] 
y = [] 
for i,v in r_enumerate(x): 
    if v != 3: 
     y.append(x.pop(i)) 
    print 'i=%d, v=%d, x=%s, y=%s' %(i,v,x,y) 


かはxrangeと:

x = [1,2,3,4,5] 
y = [] 
for i in xrange(len(x)-1,-1,-1): 
    if x[i] != 3: 
     y.append(x.pop(i)) 
    print 'i=%d, x=%s, y=%s' %(i,x,y) 
1

私はこれが受け入れ答えを持つが、それでも一緒に来るかもしれないものの古いポストである知っている...

いくつかの以前の回答は、反復中に反復可能性を変更することは好ましくないことを示しています。しかし、何が起こっているのかを強調する方法として...

>>> x=[1,2,3,4,5] 
>>> for i in x: 
...  print i, x.index(i) 
...  x.remove(i) 
...  print x 
... 
1 0 
[2, 3, 4, 5] 
3 1 
[2, 4, 5] 
5 2 
[2, 4] 

うまくいけば、視覚的に役立ちます。