一个列表循环的问题,困扰了半个小时,我也是醉了,值得深思
下面开始提需求:
一个列表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}]
完事儿!!!