1. 程式人生 > >使用enumerate()函式時,慣性思維帶來的錯誤

使用enumerate()函式時,慣性思維帶來的錯誤

防止enumerate()迴圈後出錯

enumerate和for迴圈

enumerate和for迴圈很像,for迴圈是遍歷一個列表裡所有的元素,enumerate()對於一個可迭代的(iterable)/可遍歷的物件(如列表、字串),enumerate將其組成一個索引序列,利用它可以同時獲得索引(標籤)和值(元素),

當遍歷列表時有刪除操作時

  • 程式碼
a=["soccer","basketball","pingpong","run","play","game"]
b=[]
for num,i in enumerate(a):
    print(num,i)
    if len(i) > 6:  
        print('刪除'+i)
        del a[num]
    else:
        b.append(i)   
print(a)       
print(b)
  • 執行結果
    [‘soccer’, ‘pingpong’, ‘run’, ‘play’, ‘game’]
    [‘soccer’, ‘run’, ‘play’, ‘game’]
  • 解釋
    發現結果中滿足條件(長度大於6)的ping-pong並沒有被刪除,下面模擬一下enumerate執行過程,enumerate的過程並不一定是按每個元素過濾一遍,而是按每個索引(0,1,2,3…)過濾一遍。
    迴圈過程如下:
索引 第一次迴圈 第二次迴圈 第三次迴圈 第四次 第五次 第六次
0 soccer soccer soccer soccer soccer soccer
1 basketball pingpong pingpong pingpong pingpong pingpong
2 pingpong run run run run run
3 run play play play play play
4 play game game game game game
5 game

第一次迴圈標籤為0的soccer元素,不滿足條件(長度<6),保留元素。第二次迴圈索引為1的basketball元素,滿足條件,刪除元素。在第三次迴圈開始的時候,由於上一個迴圈刪除了basketball元素,所以basketball後面的元素索引都會減一。所以pingpong元素的索引由原來的2,變成了1。但第二次迴圈已經遍歷了索引為1的元素,所以第三次迴圈不會再遍歷這個索引以及對應的元素。所以滿足刪除條件的pingpong元素沒有被刪除。

解決方法

  1. 只要讓滿足刪除條件的兩個元素不挨著,那就可以刪除所有滿足條件的元素。
  2. 讓列表中的元素倒著迴圈。
a=["soccer","game","play","pingpong","run","basketball"]
b=[]

for num,i in enumerate(a):
    print(num,i)
    if len(i) > 6:  
        print('刪除'+i)
        del a[num]
    else:
        b.append(i)
    
print(a)       
print(b)

執行結果:
[‘soccer’, ‘game’, ‘play’, ‘run’]
[‘soccer’, ‘game’, ‘play’]
為什麼b列表只有兩個元素呢?
因為刪除元素後,run的新索引之前被遍歷過了,所以就自動略過了。

dataframe的索引

資料框(dataframe)每一行對應的標籤是不會變化的

np.random.seed(123)
df = pd.DataFrame(np.random.randn(5,3))
df.drop([0],axis=1,inplace=True)
print(df)

執行結果:
上面的資料是原始資料,下面的資料是刪除行後的資料
第二行被刪除了,但是每一行原來對應的索引還是原來的索引。