Ad
Still have questions? Join our Discord server and get real time help.
Log in to vote
7

Why does the length of this table = 0?

Asked by
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)

Thanks for your time.

2 answers

Log in to vote
6
Answered by
Shawnyg 4241 Trusted Badge of Merit Snack Break Moderation Voter Administrator Community Moderator Super Administrator
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
Ad
Log in to vote
0
Answered by
Link150 1327 Badge of Merit Moderation Voter Administrator
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".

Answer this question