(原创) cocos2d-x 3.0+ lua 学习和工作(5) : table的remove的坑

本章主要讲下,table的remove,这个东西不注意就容易被坑(被坑的飘过~~~),当然,这里是针对数组table。即用ipairs方法遍历。

星月倾心贡献~~~

看示例1:直接nil

local tbl = { 1, 2, 3, 4, 5 }

for k, v in ipairs( tbl ) do
    if v == 3 then
        tbl[k] = nil
    else
        print( "one: " .. k .. ":" .. v )
    end

end

-- 再次输出会发什么。。。
for k, v in ipairs( tbl ) do
    print( "two" .. k .. ":" .. v )
end

输出:
one: 1:1
one: 2:2
one: 4:4
one: 5:5

-- 没有输出3

再次输出:
two1:1
two2:2
-- 只输出了,1,2。

大家可以看到,再次输出时,只输出了1,2。(小白:为什么。。。)

我们在直接nil后,table的元素变成了{ [1] = 1, [2] = 2, [4] = 4, [5] = 5 },我之前已经知道,ipairs是连续顺序遍历的,查找3,不存在,结束遍历。(小白:对哦~~)

直接nil,table中的其他元素key值不会改变~~~(坑。。。)

那么有没有方法删除后,table元素重新依次排列?

这个就是我没要讲的第二个方法:table.remove()

示例2:table.remove方法删除

local tbl = { 1, 2, 3, 4, 5 }

for k, v in ipairs( tbl ) do
    if v == 3 then
        table.remove( tbl, k )
    else
        print( "one: " .. k .. ":" .. v )
    end

end

-- 再次输出会发什么。。。
for k, v in ipairs( tbl ) do
    print( "two" .. k .. ":" .. v )
end

输出:
one: 1:1
one: 2:2
one: 4:5  -- 1. 注意,这里只输出了 vlaue: 5

-- 没有输出3

再次输出:
two1:1
two2:2
two3:4  -- 2. 注意:key: 3
two4:5  -- 3. 注意:key: 4 

-- 再次输出后,key值是连续的

我们先看再次输出,再次输出可以看到所有的元素都输出了,并且key值是连续的。这就是table.remove删除方法的好处。这个没有问题~~~

现在问题来了,大家注意。(小白:什么问题。。。)

在第一个输出中,注释中可以看到只输出了5,没有输出4。(小白:什么...value: 4去那里了???)

这就是另外一个坑了~~~~(小白:好坑~~~)你以为它遍历了所有,其实它漏人了。。。

原因是:

table.remove会自动帮我们排序,remove后的tbl是 { 1, 2, 4, 5 }

但是在第一个for循环中,remove时候,k == 3,再次进入下一个语句时,k == 4, 这时的tbl[4] == 5,然后k达到最大值,结束循环。所以只输出了5,没有输出4。

小白:这个bug很简单啊,我在remove后,让 k = k - 1;这样再次进入下一个语句时,k就等于3了,就能输出4了。

星月:是吗?(小白:难道不是吗...?)

为了让小白死心,这里分析下k的值。

k的值是ipairs迭代器返回的值,就算将k = k - 1, 即人为让 k = 2 了,那么下一个调用时,迭代器仍然返回 4,即 k = 4。所以在外界改变k的值没有任何意义。(再坑一次~~~~)

(小白:好坑~~~那怎么办???)

那么有什么办法解决这个呢?

示例3:逆查找,然后调用table.remove

local tbl = { 1, 2, 3, 4, 5 }

for k = #tbl, 1, -1  do
    if tbl[k] == 3 then
        table.remove( tbl, k )
    else
        print( "one: " .. k .. ":" .. tbl[k] )
    end

end

-- 再次输出会发什么。。。
for k, v in ipairs( tbl ) do
    print( "two" .. k .. ":" .. v )
end

输出:
one: 5:5
one: 4:4
one: 2:2
one: 1:1

-- 这里所有元素全部输出了!!

-- 没有输出3

再次输出:
two1:1
two2:2
two3:4  -- 2. 注意:key: 3
two4:5  -- 3. 注意:key: 4 

-- 再次输出后,key值是连续的!!

可以第一次输出所有元素都输出了,第二次也所有元素都输出了。(小白:真的耶~~~)(星月:呕吐...)

原来大家自己分析,跟示例2的原理差不多。

本章到此结束,希望对大家有帮助。

星月倾心贡献~~~

作者使用 cocos2d-x 3.0 + lua学习和工作心得,未经作者允许,请勿转载!在此谢谢各位手下留情~~~

本文没有获得作者本人同意,不得转载,否则必追究相关责任。转载请注明出处!!~~

原文地址:http://www.cnblogs.com/wodehao0808/p/4029560.html

时间: 2024-10-22 10:08:01

(原创) cocos2d-x 3.0+ lua 学习和工作(5) : table的remove的坑的相关文章

(原创)cocos2d-x 3.0+ lua 学习和工作(2) : 单一继承简单介绍

-- 星月相随倾心贡献~~~ -- 本章简单介绍一下:单一继承 -- 多继承本人还没有用过,主要是lua多继承感觉不好用~~~个人感觉~~~大汗~! -- example: local Base = class( "Base" ) Base.__index = Base function Base:ctor(...) print( self.__cname ) -- 输出:类名字.class( "xxx" ), self._cname 就是 xxx end func

(原创) cocos2d-x 3.0+ lua 学习和工作(4) : 公共函数(5): 返回指定表格中的所有键(key):table.keys

这里的函数主要用来做:返回指定表格中所有的键.参考资料为quick_cocos. 星月倾心贡献~~~ --[[ -- 返回指定表格中的所有键(key) -- example: local t = ( a = 1, b = 2, c = 3 ) local keys = table.keys( t ) -- keys = { "a", "b", "c" } -- @param t 要检查的表格(t表示是table) -- @param table

(原创) cocos2d-x 3.0+ lua 学习和工作(4) : 公共函数(7): 其他table方法

看了下其他的table方法,好像没有什么好说的,注释里已经写的很明白了,这里就不罗嗦了~(小白:懒...).参考资料为quick_cocos. 星月倾心贡献~~~ --[[ -- 返回指定表格中的所有值(value) -- example local t = { a = 1, b = 2, c = 3 } local values = table.values( t ) -- values = { 1, 2, 3 } -- @parame t 要检查的表格(t表示是table) -- @para

(原创) cocos2d-x 3.0+ lua 学习和工作(4) : 公共函数(8): 生成只读table

这个函数的作用是:生成只读table. --[[ -- 生成只读table -- @param table t 需要不允许修改的table example: local tb = {"星期一", "星期二", "星期日"} local days = readOnly( tb ); days[2] = "星期三哪去了啊?" ; "[string \"Functions.lua\"]:466: 别修改

(原创) cocos2d-x 3.0+ lua 学习和工作(4) : 公共函数(6): 合并表格:table.merge

这里的函数主要用来做:合并表格.参考资料为quick_cocos. 星月倾心贡献~~~ --[[ -- 将 来源表格 中所有键及值复制到 目标表格 对象中,如果存在同名键,则覆盖其值 -- example local tDest = { a = 1, b = 2 } local tSrc = { c = 3, d = 4 } table.merge( tDest, tSrc ) -- tDest = { a = 1, b = 2, c = 3, d = 4 } -- @param tDest 目

(原创) cocos2d-x 3.0+ lua 学习和工作(4) : 公共函数(4): handler

这里的函数主要用来做:回调函数.参考资料为quick_cocos. 星月倾心贡献~~~ --[[ -- 将lua对象及方法包装为一个匿名函数 -- 许多功能需要传入一个 Lua 函数做参数,然后在特定事件发生时就会调用传入的函数.例如触摸事件.帧事件等等. -- example: local MyScene = class( "MyScene", function() ) return cc.Layer:create() end ) function MyScene:ctor() se

(原创) cocos2d-x 3.0+ lua 学习和工作(4) : 公共函数(5): 计算table元素个数:table.nums

这里的函数主要用来做:计算table元素个数.参考资料为quick_cocos. 星月倾心贡献~~~ 我们先看一段代码 local tbl = { [1] = 2, [2] = 2, [3] = 3 } print( "tbl length is " .. #tbl ) 这段代码是获得tbl的长度,即元素个数. 输出: tbl length is 3 拥有三个元素,没有问题.我们注意到元素的下标是,即key值是:1, 2, 3.即tbl[1], tbl[2], tbl[3].如果,我们

(原创) cocos2d-x 3.0+ lua 学习和工作(4) : 公共函数(3): 深度克隆clone()

先上一段代码: local tbl = { ["a"] = 1, ["b"] = 2 } local cpy = tbl for k, v in pairs( tbl ) do print( "tab: " .. k .. ":".. v ) -- 打印tbl里的元素值 end for k, v in pairs( cpy ) do print( "cpy: " .. k .. ":".

(原创) cocos2d-x 3.0+ lua 学习和工作(4) : 公共函数(2): 检查

这里的函数主要用来做:检查操作.参考资料为quick_cocos. 星月倾心贡献~~~ --[[ -- 检查并转换为数值,转换失败则返回 0 -- @param value 要检查并转换的值 -- @param base 进制,默认为十进制 -- @return number 返回的数值 --]] function checkNumber( value, base ) return tonumber( value, base ) or 0 end --[[ -- 检查并转换为布尔值, 除了nil