如何删除Lua表中的所有元素?

27

如何删除Lua表中的所有元素?我不想这样做:

t = {}
table.insert(t, 1)
t = {}  -- this assigns a new pointer to t

我希望保留指向t的相同指针,但删除t中的所有元素。

我尝试过:

t = {}
table.insert(t, 1)
for i,v in ipairs(t) do table.remove(t, i) end

上面的内容是否有效?还需要其他什么吗?

3
我猜情况是在一个以它作为参数的函数中清空一个表格。那么这个问题很好,+1。起初我对“指针”一词感到困惑,因为它存在于C代码中,不应该出现在Lua代码中。你的意思是“引用”或其他什么。 - AndersH
6个回答

42
for k in pairs (t) do
    t [k] = nil
end

这也可以工作 - 如果表不是在整个数组中使用,您可能会遇到使用ipairs时的困难。


27

表元素插入和删除的性能比较

表的大小为10000000

[1] 使用while和rawset函数

while #t ~= 0 do rawset(t, #t, nil) end

花费时间 = 0.677220

[2] next 和 rawset

for k in next, t do rawset(t, k, nil) end

花费时间 = 0.344533

[3] ipairs和rawset

for i, v in ipairs(t) do t[i] = nil end

花费时间 = 0.012450

[4] for循环,rawset函数

count = #t
for i=0, count do t[i]=nil end

花费的时间 = 0.009308

表格元素插入

[1] 表格插入函数

for i=0, 10000000 do    table.insert(t, i, i) end

花费时间 = 1.0590489

[2] 使用 #t

for i=0, 10000000 do    t[#t+1] = i end

花费时间 = 0.703731

[3] for循环,rawset函数

for i=0, 10000000 do rawset(t, i, i) end

花费时间 = 0.100010

结果。

最快的删除:4

最快的插入:3


这是一个全面而有效的答案。 - Klaatu von Schlacker

15

最简单和性能最佳的方法:

for k,v in pairs(tab) do tab[k]=nil end

你提出的方法并不可行: table.remove 移除元素后会使剩下的元素向前移动填补空位,从而破坏了对表的遍历。查看next函数的描述以获取更多信息。


4

为了更快的版本,忽略__pairs元方法:

local next = next
local k = next(tab)
while k ~= nil do
  tab[k] = nil
  k = next(tab, k)
end

编辑:正如@siffiejoe在评论中提到的,这可以通过将pairs调用替换为其对表格的默认返回值next方法和表本身来简化为一个for循环。此外,为了避免所有元方法,使用rawset方法进行表索引分配:

for k in next, tab do rawset(tab, k, nil) end

2
或者只需使用for k in next,tab do tab[k] = nil end - siffiejoe
2
根据Lua优化指南https://www.lua.org/gems/sample.pdf,这种方法令人惊讶地糟糕。问题在于将元素设置为nil通常不会从表中删除它,直到下一次调整大小。next的实现必须在返回之前搜索所有nil,使其成为意外的O(n^2)。 - AHelps
@AHelps 感谢您指出这一点!我的较长的 while 版本没有这个问题,因为 next 是用前一个索引调用的。@siffiejoe 的版本缺少了这部分,所以它执行了较慢的版本。我会对答案进行解释性编辑。 - bonsaiviking
@AHelps 其实,我撤回之前的说法:通用的“for循环”结构会自动将迭代器函数的返回值作为下一次迭代中函数的第二个参数。因此,第一次迭代是k = next(tab, nil),但下一次迭代是k = next(tab, k),这避免了完整的遍历。 - bonsaiviking

1

#table是表的大小,因此如果t = {1,2,3},那么#t = 3

所以你可以使用这段代码来移除元素

while #t ~= 0 do rawset(t, #t, nil) end

你将遍历整个表并删除每个元素,最终得到一个空表。


0
将变量更改为其他任何值,然后再转换为一个表格,这样它就为空了。
t = {1,2,3}
print(t[1])      -- 1
t = "Hello World"
print(t)          -- Hello World
t = {}
print(t[1])       -- nil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接