Getting size of a table with table.getsize(table) what is a hash count?

I'm trying to get the length of "table" to use as a max a randomizer

local message = {}
message[1] = "one"
message[2] = "two"
message[3] = "three"
local numberOfMessages = table.getsize(message) --returns the number 4

i guess i can subtract 1 when i use it but why does this happen?

I read the docs

[f] table.getsize(table)
Returns the size of the given table as a multiple values ( arrayCount , hashCount ).

What does it mean when it says it returns multiple values? is it coming back as an array?
I tried to use numberOfMessages.arrayCount and numberOfMessages.hashCount to try to get these values

What is a hash count?

Lua "multiple value" returns are weird. They work as follows, assigned to whatever two variables you choose:

local myArrayCount
local myHashCount

myArrayCount, myHashcount = table.getsize(myTable)

As for the two parts, Lua tables have integer keys (like you might expect from an array) which you can either assign the way you have done, or as follows:

local message = {"one", "two", "three"}

That's the "array" part.

But Lua tables can also contain named keys like this:

local message = {startMessage = "one", winMessage = "two", loseMessage = "three"}

Or format it on multiple lines for readabilty:

local message = {
	startMessage = "one", 
	winMessage = "two",
	loseMessage = "three"
}

Or you can do it like this (among other ways):

local message = {}
message.startMessage = "one"
message.winMessage = "two"
message.loseMessage = "three"

That's the "hash" part. (And you can't predict what order those will be stored at—the order is practically random—so don't try to access them by iterating through [integer] keys. Use message.startMessage or message[startMessage]. )

There's even more to Lua tables than that... they are still strange to me, but sometimes super useful! You can even nest tables inside tables.

Thank you for the detailed response, i'm curious why they call it a hash, in javascript thats an object.

I'm getting a strange error though when i list for 3 messages

message[1] = "one" 
message[2] = "two"
message[3] = "three"

returns an arrayCount of 4

message[1] = "one" 
message[2] = "two"

returns an arrayCount of 2

and when i make 6 it makes an arrayCount of 8 total bonkers, i used table.create to explicit set the size and that works but kinda defeats the purpose if i have to know how many are in it to iterate through it.

I've had success with simply #message... but my tables are hard-coded data and don't change, so I could count them by hand if I wanted to bother.

Apparently the only reliable way to get the size of a table is to iterate it and increment a counter. But luckily you can iterate without knowing the size:

for index, value in ipairs(message) do
     print(index, value)
end

That's for numeric indices. For named keys you'd use pairs() instead of ipairs().

Lua is still strange to me, including tables starting at 1 instead of 0... but these quirks do have their benefits!

1 Like

yes that works, thank you so much

1 Like

It's likely called hash count as the non integer keys are stored in some kind of hash table behind the scenes. A hash function basically converts some sorting-unfriendly value like a string or object into a uniformly random number. A hash table then uses that value as a key to store the data. They are very good at efficiently storing and retrieving data and often used for storing strings or objects. Wikipedia article on them

2 Likes

As I recall, we added table.getsize() for Shaun Inman back when he was fixing performance problems in Crankin' and Ratcheteer, before he gave up on Lua with its automatic memory management and ported them to C. The returned values were only ever intended to be used as arguments to the table.create() function. I think what happened with the docs is we used to have those functions paired but they got split up when we reformatted Inside Playdate around the time we released the SDK. I'll file an issue to explain that better there. Thanks for pointing this out!

2 Likes

Just discovered this topic and think I could give a bit of extra context in case someone stumbles on this in the future: The getsize seems to be returning the allocated or "reserved" space for the table, not the number of entries that are currently in use. I found a good explanation of how tables work on page 19 of this PDF: Lua Performance Tips. It specifically explains why the arrayCount goes from 2 to 4 to 8, rather than giving you the 2, 3, 4 you were expecting.

In your case, you are using the array part of the table (i.e. your keys are positive integers), so you should be able to use #numberOfMessages to count the length as well. Be aware that this operator only works correctly for continuous sequences, which will usually be the case, but for a table like { "one", "two", "three", nil, "five" } the count would be reported as 3 and not 4.

For non-integer keys (that are part of the hash part of the table), you'll indeed have to manually count the entries using pairs().

n.b. The "object" in JavaScript is also implemented as a hashmap. My guess is that since a Lua table is a bit of a mix of 2 datatypes, they choose to be more explicit with their naming.

1 Like