How to iterate/pick randomly from associative arrays?

If I have…

[lua]
local mRand = math.random
local t = {1,2,3,4,5,6,7,8,9}
local a = {}
for i=1, 5 do
local num = mRand(1, #t)
a[#a +1] = t[num]
end

[/lua]

But what if I have…
[lua]
local t = { [“a”] = 1, [“b”] = 2, etc etc… }
local a = {}
for i = 1, 5 do
local num = mRand(1, #t)
a[#a +1] = t[num]
end
[/lua]
This doesn’t work…
How do I pick randomly from associative arrays?

I would use a for k, v in pairs(t) loop and create an indexed loop where each array is the key from the table you care about, and then do a random number, look it up in the indexed table, get the key then get the value.

to clarify rob’s answer:

local keys, i = {}, 1 for k,\_ in pairs(t) do  keys[i] = k  i= i+1 end -- then local m for i=1,5 do   m= math.random(1,#keys) a[i] = t[keys[m] ] end

Ok, I’ve put this aside for a bit and got a copy of Programming in Lua so I could read up on things.

I’ll try that, thanks.

I read that, can’t recall where, but that it’s faster and uses less memory to do this(table inserts in general)

[lua]

local mRand = math.random

local count = mRand(3,7) 

local t1 = { {“a”, 1}, {“o”, 1}, {“p”, 2}, {“v”, 2}, {“i”, 1}, {“c”, 5}, {“b”, 1}, {“x”,9}, {“w”, 1}, {“m”, 2}, {“e”, 3} }

local t2 = {}

for i = 1, count do

     local val = mRand(1, #t1)

     t2[#t2 + 1] = t1[val]

end

print_r(t2)

[/lua]

another test…

[lua]

local mRand = math.random

local count = mRand(3,7) 

local t1 = { {“a”, 1}, {“o”, 1}, {“p”, 2}, {“v”, 2}, {“i”, 1}, {“c”, 5}, {“b”, 1}, {“x”,9}, {“w”, 1}, {“m”, 2}, {“e”, 3} }

local t2 = {}

local val = mRand(1, #t1)

for i = 1, count do

     t2[#t2 + 1] = t1[val]

end

print_r(t2)

[/lua]

another test…

[lua]

local mRand = math.random

local count = mRand(3,7) 

local t1 = { {“a”, 1}, {“o”, 1}, {“p”, 2}, {“v”, 2}, {“i”, 1}, {“c”, 5}, {“b”, 1}, {“x”,9}, {“w”, 1}, {“m”, 2}, {“e”, 3} }

local t2 = {}

for i = 1, count do

     t2[#t2 + 1] = t1[mRand(1, #t1)]

end

print_r(t2)

[/lua]

Though I noticed that sometimes a few entries are empty in my print_r( ), the empty ones show

[4]  => table: 0x10d4c34f0 {*table =0x112d23b60} etc.

It inserts a table but not the values inside, how come? is this method too fast? where did I go wrong with my randomization???

this btw doesn’t give empty entries, however I do want to make the random thing work for my own sanity… :slight_smile:

[lua]

local mRand = math.random

local count = mRand(3,7) 

local t1 = { {“a”, 1}, {“o”, 1}, {“p”, 2}, {“v”, 2}, {“i”, 1}, {“c”, 5}, {“b”, 1}, {“x”,9}, {“w”, 1}, {“m”, 2}, {“e”, 3} }

local t2 = {}

for i = 1, count do

     t2[#t2 + 1] = t1[i]

end

print_r(t2)

[/lua]

Thanks for the help

It’s not empty. Tables are always passed by reference to it (address in memory they reside), so 0x10d4c34f0 is address of table. When you try to print table then there is no way to do it, instead lua will print it’s address.

local t1 = { {"a", 1}, {"o", 1}, {"p", 2}, {"v", 2}, {"i", 1}, {"c", 5}, {"b", 1}, {"x",9}, {"w", 1}, {"m", 2}, {"e", 3} }

it is table of tables, so t1[1] = { “a”, 1 }, then t1[1][1] = “a” and t1[1][2] = 1

In your second metod t2 will be always filled with the same elements - each element will be the same.

Thanks, i ran a test in the simulator and all my entries did show up. I just got a bit confused because the terminal showed that. 

thanks.

I would use a for k, v in pairs(t) loop and create an indexed loop where each array is the key from the table you care about, and then do a random number, look it up in the indexed table, get the key then get the value.

to clarify rob’s answer:

local keys, i = {}, 1 for k,\_ in pairs(t) do  keys[i] = k  i= i+1 end -- then local m for i=1,5 do   m= math.random(1,#keys) a[i] = t[keys[m] ] end

Ok, I’ve put this aside for a bit and got a copy of Programming in Lua so I could read up on things.

I’ll try that, thanks.

I read that, can’t recall where, but that it’s faster and uses less memory to do this(table inserts in general)

[lua]

local mRand = math.random

local count = mRand(3,7) 

local t1 = { {“a”, 1}, {“o”, 1}, {“p”, 2}, {“v”, 2}, {“i”, 1}, {“c”, 5}, {“b”, 1}, {“x”,9}, {“w”, 1}, {“m”, 2}, {“e”, 3} }

local t2 = {}

for i = 1, count do

     local val = mRand(1, #t1)

     t2[#t2 + 1] = t1[val]

end

print_r(t2)

[/lua]

another test…

[lua]

local mRand = math.random

local count = mRand(3,7) 

local t1 = { {“a”, 1}, {“o”, 1}, {“p”, 2}, {“v”, 2}, {“i”, 1}, {“c”, 5}, {“b”, 1}, {“x”,9}, {“w”, 1}, {“m”, 2}, {“e”, 3} }

local t2 = {}

local val = mRand(1, #t1)

for i = 1, count do

     t2[#t2 + 1] = t1[val]

end

print_r(t2)

[/lua]

another test…

[lua]

local mRand = math.random

local count = mRand(3,7) 

local t1 = { {“a”, 1}, {“o”, 1}, {“p”, 2}, {“v”, 2}, {“i”, 1}, {“c”, 5}, {“b”, 1}, {“x”,9}, {“w”, 1}, {“m”, 2}, {“e”, 3} }

local t2 = {}

for i = 1, count do

     t2[#t2 + 1] = t1[mRand(1, #t1)]

end

print_r(t2)

[/lua]

Though I noticed that sometimes a few entries are empty in my print_r( ), the empty ones show

[4]  => table: 0x10d4c34f0 {*table =0x112d23b60} etc.

It inserts a table but not the values inside, how come? is this method too fast? where did I go wrong with my randomization???

this btw doesn’t give empty entries, however I do want to make the random thing work for my own sanity… :slight_smile:

[lua]

local mRand = math.random

local count = mRand(3,7) 

local t1 = { {“a”, 1}, {“o”, 1}, {“p”, 2}, {“v”, 2}, {“i”, 1}, {“c”, 5}, {“b”, 1}, {“x”,9}, {“w”, 1}, {“m”, 2}, {“e”, 3} }

local t2 = {}

for i = 1, count do

     t2[#t2 + 1] = t1[i]

end

print_r(t2)

[/lua]

Thanks for the help

It’s not empty. Tables are always passed by reference to it (address in memory they reside), so 0x10d4c34f0 is address of table. When you try to print table then there is no way to do it, instead lua will print it’s address.

local t1 = { {"a", 1}, {"o", 1}, {"p", 2}, {"v", 2}, {"i", 1}, {"c", 5}, {"b", 1}, {"x",9}, {"w", 1}, {"m", 2}, {"e", 3} }

it is table of tables, so t1[1] = { “a”, 1 }, then t1[1][1] = “a” and t1[1][2] = 1

In your second metod t2 will be always filled with the same elements - each element will be the same.

Thanks, i ran a test in the simulator and all my entries did show up. I just got a bit confused because the terminal showed that. 

thanks.