Still have questions? Join our Discord server and get real time help.
7

# Why does the length of this table = 0?

ausmel105 140
3 years ago

Hello all,

I was wondering why the code below prints to be 0, am I not adding an entry to the airport.airlines table?

local airport = {}

airport.destinations = {
Zakynthos = {
Name = "Zakynthos";
IATA = "ZAK"
}
}

airport.airlines = {
Airline = {
Name = "Airline";
GroupID = 1;
IATA = "AA";
Destinations = {
airport.destinations.Zakynthos;
}
}
}

print(#airport.airlines)


6
Shawnyg 4241
3 years ago
Edited 3 years ago

When using the standard Lua length operator, it counts all of the regular indexes of the table. With yours, you set your own index to be 'Airline', therefore the length operator doesn't see it.

If you were to use regular entries:

local tab = {"test","12"}
print(#tab) -- 2


it would print 2. Since you set your own index, you'd have to use a for loop to manually count them. What you're doing is establishing your own dictionary in which you define everything yourself.

local tab = {}
tab.Pi = "3.14"
tab.Cat = "Meow"

local count = 0
for i,v in pairs(tab) do
count = count + 1
end
print(count) -- prints 2


In this scenario, i represents Pi, and v represents 3.14, at least for one index. The second index, i represents Cat and v represents Meow.

0
Actually, this only happens with dictionaries. AstrealDev 698 — 3y
0
Ah, may have gotten a few of my terms mixed up. A bit tired. Shawnyg 4241 — 3y
0
3 years ago
Edited 3 years ago

Table elements with non-numerical keys won't count towards the length of the table when using either the # operator or the table.getn function.

A solution to this, although not very convenient, is to keep track of the length of the table manually:

local myTable = {
length = 0
}

myTable["key"] = "value"
myTable.length = myTable.length + 1

print(myTable.length) --> '1'


Alternatively, you could use a metatable to do it for you, but that will require an empty table to serve as a proxy:

local myTableProxy = {
length = 0
}

do
local actualTable = {}

setmetatable(myTableProxy, {
__index = actualTable,
__newindex = function(t, k, v)
local oldValue = t[k]
local newLength = t.length or 0

-- Please note that the '== nil' and ~= nil checks are
-- important in this case.
if oldValue == nil and v ~= nil then
newLength = newLength + 1
elseif oldValue ~= nil and v == nil then
newLength = newLength - 1
end

rawset(t, "length", newLength)
rawset(actualTable, k, v)
end
})
end

myTableProxy["key"] = "value"

print(myTableProxy.length) --> '1'


but I won't explain this technique any further, as it is out of the scope of this answer. This solution also makes it impossible for actualTable to contain an element with key named "length".