Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
1

How do I get a random number from a dictionary?

Asked by 9 years ago

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?

2 answers

Log in to vote
3
Answered by
BlueTaslem 18071 Moderation Voter Administrator Community Moderator Super Administrator
9 years ago

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.

0
Or you could go 't[keys[math.random(1,#keys)]]' c: Goulstem 8144 — 9y
0
Yes, but it's more illustrative of the point to give the values names BlueTaslem 18071 — 9y
0
Gracias senor! ZeptixBlade 215 — 9y
Ad
Log in to vote
1
Answered by
Unclear 1776 Moderation Voter
9 years ago

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...

Answer this question