Please read Lua Reference Manual: 3.4.7 The Length Operator
The length operator applied on a table returns a border in that table.
A border in a table t is any natural number that satisfies the
following condition:
(border == 0 or t[border] ~= nil) and t[border + 1] == nil
In words, a border is any (natural) index present in the table that is
followed by an absent index (or zero, when index 1 is absent).
A table with exactly one border is called a sequence. For instance,
the table {10, 20, 30, 40, 50} is a sequence, as it has only one
border (5). The table {10, 20, 30, nil, 50} has two borders (3 and 5),
and therefore it is not a sequence. (The nil at index 4 is called a
hole.) The table {nil, 20, 30, nil, nil, 60, nil} has three borders
(0, 3, and 6) and three holes (at indices 1, 4, and 5), so it is not a
sequence, too. The table {} is a sequence with border 0. Note that
non-natural keys do not interfere with whether a table is a sequence.
When t is a sequence, #t returns its only border, which corresponds to
the intuitive notion of the length of the sequence. When t is not a
sequence, #t can return any of its borders. (The exact one depends on
details of the internal representation of the table, which in turn can
depend on how the table was populated and the memory addresses of its
non-numeric keys.)
Applied to your examples:
local t1={}
t1[1]="Foo"
t1[2]="Bar"
t1
has only one boarder (2), because t1[2] ~= nil and t1[2+1] == nil
.
t1
has only 1 border -> t1
is a squence -> #t1
is the length of t1
.
local t2={}
t2[5]="Foo"
t2[40]="Bar"
t2
has 3 borders (0, 5, 40), because boarder == 0 and t[0+1] == nil
, t[5] ~= nil and t[5+1] == nil
, t[40]~=nil and t[40+1]==nil
t2
has more than one borders-> #t2
is any of its borders, not its length.
local t3={}
t3["A"]="Foo"
t3["B"]="Bar"
t3
has 1 border (0), because border == 0 and t3[0+1] == nil
, no more numeric keys so no more borders. t3
has only one border -> t3
is a sequence with length 0.
local t4={}
t4.A="Foo"
t4.B="Bar"
is the same as t4
as t.name
is syntactic sugar for t["name"]
. Only works for valid Lua names!
t1
is the only sequence among your examples and hence the only one #
yields the number of element for.
If you are unsure if you have a sequence you should count the elements like so:
local n = 0
for _ in pairs(t) do
n = n + 1
end
This is how you would print the boarders of a table t
:
function printBorders(t)
local borders = {}
for k in pairs(t) do
if type(k) == "number" and
t[k] ~= nil and t[k+1] == nil then
table.insert(borders, k)
end
end
if t[1] == nil then table.insert(borders, 0) end
table.sort(borders)
print(table.concat(borders, ", "))
end