一個列表循環的問題,困擾了半個小時,我也是醉了,值得深思
下面開始提需求:
一個列表mylist = [{'tag':1,'num' :5000},{'tag':2,num
: 6000},{'tag':3,num
: 3000},{'tag':4,num
: 1000} ],
列表的元素是字典,字典中有兩個key,現在需要給定一個整數,比如說6000,用這個6000來消除列表里的字典元素,比較的對象就是字典里的num值,如果num小於6000,則直接刪除該字典元素,然后6000減少num的值,接着繼續往后比較,如果后面這個整數小於num的話,就讓num減去這個整數值。最終的結果是讓原來的列表經過比較之后,使用num值消除6000這個數
下面開始貼代碼:
#!/usr/bin/env python mylist = [{'tag':1,'num' :5000},{'tag':2,"num": 6000},{'tag':3,"num": 3000},{'tag':4,"num": 1000} ] print mylist #先打印一下列表,便於比較 res = 12000 for i in mylist: if res == 0: #首先判斷res是否為0,。為0 的話表示這個整數已被減沒了,后面的元素不再處理 continue elif res >= i['num']: #如果res大於num的時候,直接刪除這個字典元素,然后res減去對應的值 res -= i['num'] mylist.remove(i) continue elif res < i['num']: #如果res小於num的時候,num直接減去res的值,然后res置0 i['num'] -= res res = 0 print mylist
當時我是根據這個邏輯來寫的代碼,執行結果如下:
原列表:[{'tag': 1, 'num': 5000}, {'tag': 2, 'num': 6000}, {'tag': 3, 'num': 3000}, {'tag': 4, 'num': 1000}] 處理后的列表:[{'tag': 2, 'num': 6000}, {'tag': 4, 'num': 1000}]
結果完全出人意料,tag2怎么沒減呢,此時的res為12000,按道理說應該會吧tag1,tag2消除了,tag3的num值為2000,現在tag1消除是正常的,tag3怎么會消除呢,更神奇的是tag2竟然沒減
下面對代碼分步打print,看看問題出在哪
for i in mylist: if res == 0: print 1,i #加print 1看看是否進入這個判斷 continue elif res >= i['num']: print 2,i #加print2 看看是否進入這個判斷 res -= i['num'] mylist.remove(i) continue elif res < i['num']: print 3,i #加print3 看看是否進入這個判斷 i['num'] -= res res = 0
執行結果:
原列表:[{'tag': 1, 'num': 5000}, {'tag': 2, 'num': 6000}, {'tag': 3, 'num': 3000}, {'tag': 4, 'num': 1000}] print的結果:2 {'tag': 1, 'num': 5000} print的結果:2 {'tag': 3, 'num': 3000} 結果:[{'tag': 2, 'num': 6000}, {'tag': 4, 'num': 1000}]
發現只有tag1和tag3進入了循環,tag2和tag4呢?
接着繼續打print
for i in mylist: print i,mylist.index(i) #打印一下元素的下標 if res == 0: print 1,i continue elif res >= i['num']: print 2,i res -= i['num'] mylist.remove(i) continue elif res < i['num']: print 3,i i['num'] -= res res = 0
執行結果:
原列表:[{'tag': 1, 'num': 5000}, {'tag': 2, 'num': 6000}, {'tag': 3, 'num': 3000}, {'tag': 4, 'num': 1000}] {'tag': 1, 'num': 5000} 0 2 {'tag': 1, 'num': 5000} {'tag': 3, 'num': 3000} 1 2 {'tag': 3, 'num': 3000} 結果:[{'tag': 2, 'num': 6000}, {'tag': 4, 'num': 1000}]
從打印結果中發現,tag1的下標索引為0,是正常的,tag3的下標按理說應該是2,怎么是1呢?
突然恍然大悟,for循環迭代列表的時候,是按照列表的下標索引來進行迭代,第一次循環下標0,拿到tag1,進行判斷處理,符合res>num那個條件,所以執行了remove操作,res同時也減去了num 變為7000,此時列表已變成mylist=[{'tag': 2, 'num': 6000}, {'tag': 3, 'num': 3000}, {'tag': 4, 'num': 1000}],for循環開始第二次循環下標為1,,此時mylist[1]是{'tag': 3, 'num': 3000},所以會處理tag3,發現res>num,所以同樣執行remove操作,把列表變成mylist=[{'tag': 2, 'num': 6000}, {'tag': 4, 'num': 1000}] ,繼續循環下標2,發現mylist列表中沒有了下面2的元素,所以就中止了循環,導致最終的結果為[{'tag': 2, 'num': 6000}, {'tag': 4, 'num': 1000}]
知道原因之后,改變一下思路,用新的列表來存儲res < num,並且減去res后的元素,還有res=0之后的所有元素。最后將新列表的值復制給原來列表,就可以達到需求
mylist = [{'tag':1,'num' :5000},{'tag':2,"num": 6000},{'tag':3,"num": 3000},{'tag':4,"num": 1000} ] print mylist res = 12000 new_list= [] new_list= [] for i in mylist: if res == 0: new_list.append(i) elif res > i['num']: res -= i['num'] elif res < i['num']: i['num'] -= res res = 0 new_list.append(i) mylist = new_list print mylist
最終結果:
原列表:[{'tag': 1, 'num': 5000}, {'tag': 2, 'num': 6000}, {'tag': 3, 'num': 3000}, {'tag': 4, 'num': 1000}] 結果:[{'tag': 3, 'num': 2000}, {'tag': 4, 'num': 1000}]
完事兒!!!