加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
ruby当中,数组和hash数据结构都可以使用迭代器。假设一个数组,遍历每一个元素,其中每访问一个元素,调用这个元素的一个方法update,使在遍历过程中又删除该数组中的某些元素,这个遍历结果会怎么样。
在Game_Map当中设置usr_events并初始化为[],update_events方法中迭代usr_events。
def update_events @events.each_value {|event| event.update } @common_events.each {|event| event.update } @usr_events.each {|event| event.update} end
def update_events
@events.each_value {|event| event.update }
@common_events.each {|event| event.update }
@usr_events.each {|event| event.update}
end
然后写一个如下的测试类:
然后我们初始化3个Test类的实例id,i各为0,1,2。然后在一开始的时候加入game_map.usr_events。
然后我们预测一下结果,理想情况下是0,1,2,1,2,2 这样的,一轮删除一个元素。0,1,2第一轮;1,2第二轮;2第三轮的。
实际结果却是如下:
0,2,1,2,1,2这种。
分析原因:
我们可以假设这种迭代器是没有考虑在遍历过程中还会删除某些元素的。那么我估计它会是这样实现的。
i=0; while i<usr_events.size usr_events[i].update i+=1; end
i=0;
while i<usr_events.size
usr_events[i].update
i+=1;
end
那么就会出此类问题。一开始数组是[0,1,2]这样一个结构。i=0的时候遍历0号元素,结果0号元素在执行delete的时候删除了自身导致整个数组结构成了[1,2]。但是代码并没有理会这层结构变化依然将i++;i=1的时候遍历的元素是2号元素,这样就导致了在这次遍历过程中忽略了1号元素。所以在上面那个例子显示0过后不是1而是跳过了1显示2了。
总结:
在遍历数组的时候最好不要删除元素和往数组当中插入元素,这会导致数组遍历混乱,绝对不是你想要的结果。如果向我上面那种在事件中动态添加删除事件,假设总事件是n,那么最坏情况下可能有一个事件会遍历了(1/4)n^2才会得到一次遍历机会。在巨量添加事件的情况下可能会导致巨大的延迟。
|