リストの開始長さまでの範囲をループしながら、リストの長さを変更しています。リストから 1 つの項目を削除すると、最後のインデックスは無効になります。
現在のインデックスのリストから項目が削除されるため、残りのリスト インデックスはシフトします。index にあったものがi + 1
indexi
になり、ループ インデックスは役に立たなくなりました。
最後になりましたが、 の最後のインデックスまでループしていますが、それでもtest
アクセスしようとしています。test[i + 1]
リストから要素を削除していなくても、そのインデックスは存在しません。
ループを使用して、while
やりたいことを達成できます。
test = ['aac', 'aad', 'aac', 'asd', 'msc']
i = 0
while i < len(test) - 1:
if test[i][:2] == test[i+1][:2]:
del test[i]
continue
i += 1
ループの反復ごとに新しいi
長さに対してテストされ、削除された要素がない場合にのみインクリメントされます。反復ごとにテストする必要があるため、ループの長さから 1 を引いた長さに制限されていることに注意してください。i
test[i + 1]
del test[i]
;を使用していることに注意してください。削除する値を再度検索するためにリストをスキャンする必要はありません。これは、値がリストに複数回表示され、後のインスタンスのみを削除する必要がある場合にも、微妙なバグにつながる可能性があります。たとえば、['aac', 'foo', 'aac', 'aad']
結果は['aac', 'foo', 'aad']
ではなく ['foo', 'aac', 'aad']
にtest.remove(test[i])
なります。
デモ:
>>> test = ['aac', 'aad', 'aac', 'asd', 'msc']
>>> i = 0
>>> while i < len(test) - 1:
... if test[i][:2] == test[i+1][:2]:
... del test[i]
... continue
... i += 1
...
>>> test
['aac', 'asd', 'msc']
リスト内包表記を使用して、縮小リストの問題を回避できます。
>>> [t for i, t in enumerate(test) if i == len(test) - 1 or t[:2] != test[i + 1][:2]]
['aac', 'asd', 'msc']
どちらの方法でも、入力リストを 1 回ループするだけで済みます。