【问题标题】:Special cases for table.removetable.remove 的特殊情况
【发布时间】:2016-10-23 21:29:24
【问题描述】:

table.removeThe reference manual 说:

table.remove (list [, pos])

list 中删除pos 位置的元素,返回被删除元素的值。当pos1#list之间的整数时,将元素list[pos+1]list[pos+2]、···、list[#list]向下移动并擦除元素list[#list];当#list0#list + 1时,索引pos也可以是0;在这些情况下,该函数会删除元素 list[pos]

pos0#list + 1 的最后两个特殊情况让我很感兴趣。


pos 的示例代码为0

local t1 = {[0] = 'foo'}
table.remove(t1, 0)

在这种情况下,元素 t1[0] 被删除。


pos 的示例代码为#list + 1

local t2 = {'foo', 'bar', 'baz'}
table.remove(t2, #t2 + 1)

在这种情况下,什么都没有改变,除了语句不会引发错误。


我的理解正确吗?这两种特殊情况在实践中什么时候有用?

我还注意到这两种情况是从 Lua 5.2 开始添加的

【问题讨论】:

  • @Babyy 长度为t2
  • 在许多情况下table.remove(t, 1)table.remove(t, #t) 应该更好地有效,即使#t == 0,这就是引入这些特殊情况的原因。
  • 好像是在Lua 5.2.2 的rc2 和rc3 之间添加的:lua.2524044.n2.nabble.com/…

标签: lua lua-table


【解决方案1】:

表通过匹配键和值来工作。默认情况下,键从 1 开始并转到#list。所有未定义的键的值都是 nil。

t = {}
print(t[1])
>>nil

所以你的代码只是在 #t + 1 中返回 nil

实际上,表格通常从 1 开始。但是在某些应用程序中,例如图形,从 0 开始可能更有意义。

【讨论】:

    【解决方案2】:

    最后两个特殊情况有助于在5.2 版本中设置和定义边界。 table.remove 的其他更改与这样做的原因有关。看看吧!

    -- Lua 5.1 version
    t = {'foo', 'bar' , 'baz'}
    
    local v = table.remove(t, 1)
    print(v) 
    >>nil
    table.remove(t, 7)
    -- no crash or error message
    

    -- Lua 5.2 version
    t = {'foo', 'bar' , 'baz'}
    
    local v = table.remove(t, 1)
    print(v) 
    >>foo
    table.remove(t, 7)
    >>stdin:1 bad argument #1 to 'remove' (position out of bounds)
    

    当用户在5.2中调用table.remove时,该值会从表中移除并返回。在 5.1 中,该值仅被删除。 此外,在 5.2 版本中,当用户尝试从超出范围的位置移除元素时会生成错误消息。

    这与特殊情况有什么关系?如果他们不包括在内,那就太好了

    #list0时,索引pos也可以是0

    到参数,然后在空表上使用table.remove(t) 时会崩溃。请记住,表是异构的,并且在很多情况下同时用作数组和哈希映射!有时希望在保留哈希映射的同时摆脱数组部分。为此,

    while table.remove(t) do end  -- ends when the t runs out of elements at t[0]  
    

    但有一个警告!如果#list > 0 在使用table.remove(list, 0) 时会崩溃! #list 必须等于 0

    -- Lua 5.2 version
    t = {'foo', 'bar' , 'baz'}
    
    table.remove(t, 0) -- #t is 3
    >>stdin:1 bad argument #1 to 'remove' (position out of bounds)
    table.remove(t)    -- baz
    table.remove(t)    -- bar
    table.remove(t)    -- foo
    -- #t is now 0
    table.remove(t, 0) -- nil
    -- nothing happens
    

    最后一个特殊情况#list + 1 只是为了在修剪列表时使语法更清晰。不必执行for 循环将元素擦除到pos,您可以这样做,

    -- 7 is just a random number I picked
    while table.remove(t, 7) do end  -- this will end when the t[7] = nil (aka #t + 1)   
    

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-21
      • 2021-04-04
      • 2018-11-19
      • 2012-07-13
      • 2016-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多