27

How do I delete all elements inside a Lua table? I don't want to do:

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

I want to retain the same pointer to t, but delete all elements within t.

I tried:

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

Is the above valid? Or is something else needed?

greatwolf
  • 20,287
  • 13
  • 71
  • 105
bob
  • 1,941
  • 6
  • 26
  • 36
  • 3
    I guess the situation is to empty a table in a function taking it as a parameter. Then the question is a good one, +1. I was at first confused about the word "pointer", which exists in c-code and shouldn't be mentioned in Lua-code. You mean "reference" or something. – AndersH Feb 03 '11 at 21:13

6 Answers6

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

Will also work - you may have difficulty with ipairs if the table isn't used as an array throughout.

jpjacobs
  • 9,359
  • 36
  • 45
cbz
  • 1,696
  • 1
  • 15
  • 19
27

Table elements insert and remove performance compare

The Table size count 10000000

[1] while and rawset

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

spent time = 0.677220

[2] next and rawset

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

spent time = 0.344533

[3] ipairs and rawset

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

spent time = 0.012450

[4] for, rawset

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

spent time = 0.009308

Table elemnets insert

[1] table insert function

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

spent time = 1.0590489

[2] use #t

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

spent time = 0.703731

[3] for, rawset

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

spent time = 0.100010

result.

Fastest remove : 4

Fastest insert : 3

Community
  • 1
  • 1
gogothing
  • 309
  • 3
  • 7
15

easiest and most performant:

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

What you suggest isn't usable: table.remove shifts the remaining elements to close the hole, and thus messes up the table traversal. See the description for the next function for more info

jpjacobs
  • 9,359
  • 36
  • 45
4

For a faster version that ignores the __pairs metamethod:

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

EDIT: As @siffiejoe mentions in the comments, this can be simplified back into a for loop by replacing the pairs call with its default return value for tables: the next method and the table itself. Additionally, to avoid all metamethods, use the rawset method for table index assignment:

for k in next, tab do rawset(tab, k, nil) end
bonsaiviking
  • 5,825
  • 1
  • 20
  • 35
  • 2
    Or just `for k in next,tab do tab[k] = nil end` – siffiejoe Dec 04 '14 at 08:47
  • 2
    According to https://www.lua.org/gems/sample.pdf (a Lua optimization guide), this method is surprisingly terrible. The problem is that setting an element to nil _typically does not delete it from the table_ until the next resize. The implementation of next has to search through all the nils before it returns, making this a surprise O(n^2). – AHelps Sep 15 '18 at 22:57
  • @AHelps Thanks for pointing that out! My longer `while` version doesn't suffer from this because `next` is called with a previous index. @siffiejoe's version is missing that part, so it does the slow version. I'll make an explanatory edit to the answer. – bonsaiviking Sep 17 '18 at 14:48
  • @AHelps actually, I take that back: the "generic `for` loop" construct automatically takes the return value of the iterator function as the second parameter to the function in the next iteration. So first iteration is `k = next(tab, nil)`, but the next iteration is `k = next(tab, k)`, which avoids the full traversal. – bonsaiviking Sep 17 '18 at 14:55
1

#table is the table size and so if t = {1,2,3} then #t = 3

So you can use this code to remove the elements

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

You will go through the table and remove each element and you get an empty table in the end.

meneldal
  • 1,717
  • 1
  • 21
  • 30
gogothing
  • 309
  • 3
  • 7
0

Change the variable to anything else and then back to a table, so then it is empty.

t = {1,2,3}
print(t[1])      -- 1
t = "Hello World"
print(t)          -- Hello World
t = {}
print(t[1])       -- nil
A. Kniesel
  • 135
  • 1
  • 7