Lua tables are general data structures that can be viewed as both being 'array-like' and 'map-like'. The idea is that you can use them efficiently as resize-able arrays with integer indices, but can also index them with any other value as a hash map.
pairs(t)
gives a general iterator over all the keys and values in a table, numerical or not, in no particular order; ipairs(t)
goes over the array part, in order.
Tables can contain a mixture of array and map entries:
t = {fred='one',[0]=1; 10,20,30,40}
The semi-colon is not required, it can be used as an alternative separator in table constructors. Just because 0
is a numerical index does not mean it is an array index! By definition, these go from 1
to
#t
.
These are equivalent ways to access the array elements:
for i,v in ipairs(t) do f(i,v) end for i=1,#t do f(i,t[i]) end
Lua tables naturally express sparse arrays:
t = {[1] = 200, [2] = 300, [6] = 400, [13] = 500}
n this case, #t
is unreliable, since then length operator #
is only defined for non-sparse arrays (arrays without holes). If you wish to keep track of the size of a sparse array, then it is best to keep and increment a counter:
t[idx] = val;
t.n = t.n + 1
It is a little awkward to iterate over only the non-array part of a table:
local n = #t for k,v in pairs(t) do
if type(k) ~= 'number' or k < 1 or k > n then
print(k,v)
end end
Why not have a special iterator for this? The reason is that arrays having array parts and hash parts is an implementation detail, not part of the specification. (It is straightforward to express the above as a custom iterator.)