With a normal table, you could just do;
local t = {"red", "blue"} print(math.random(1, #t))
and it will work. But in a dictionary, it doesn't.
local t = {red = 0, blue = 0} print(math.random(1, #t)) -->bad argument #2 to 'random' (interval is empty)
Doing further tests shows that the table doesn't even have a length, which doesn't really make sense.
local t = {red = 0, blue = 0} print(#t) --> 0
Of course, I could do something like:
local t = {red = 0, blue = 0} local rand = math.random(1,2) if rand == 1 then print("red was chosen") else print("blue was chosen") end
but this is really messy once the table gets any bigger.
Is there any way I can choose a random number from a dictionary efficiently?
The #
operator tells you how many elements can be indexed by going list[1]
, list[2]
, ..., list[#list]
.
That means if there isn't something at [1]
, #
is going to answer with 0
How would having a length of 2 for {red = 5, blue = 7}
be helpful, ever? It doesn't tell you where to find anything in the list, or really much anything else about the list -- and it would cause things that use #
to completely mess up.
The most straight forward way to select a random element from a dictionary is to make a list of all of the keys, and then pick a random key from that list:
local t = {red = 0, blue = 0} local keys = {} for key, _ in pairs(t) do table.insert(keys, key) end local randomKey = keys[math.random(#keys)] print("Random key: ", randomKey) print("Thing there: ", t[ randomKey ] )
You can then just ask what's at that random key to get a random value.
What you could do is take advantage of hash-table lookup by just making an array of the table's keys. This is just a matter of using what you already know to solve a problem you think you haven't encountered quite yet.
For example...
local t = {red = 0, blue = 0} -- original table local index = 1 local keys = { } -- array of table keys for key, _ in next, t do -- iterate through all key-value pairs keys[index] = key -- add to key array index = index + 1 end
Then, it's just a matter of getting a random key from an array.
local randomKey = keys[math.random(#keys)] local randomValue = t[randomKey]
Just keep in mind that even if a method may look bad, if you can't find any better solution with the resources you have it must be the best one available to you even if you don't like it. After all, completing a task is better than never completing it at all...