This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Agoldfish's profile picture

How To Use Math.random To Randomize The Contents Of A Table? [solved!]

Started by Agoldfish, 13 November 2013 - 04:35 PM
Agoldfish #1
Posted 13 November 2013 - 05:35 PM
Hello. It seems I have run into a simple problem. I can't use math.random from a table. I tried the following methods.

Method 1

local myTable = {1, 2, 3, 4, 5}
math.random(myTable)
Didn't work.

Method 2

local myTable = {1, 2, 3, 4, 5}
math.random(myTable[1-5] --#The number of numbers in the table.
That didn't work either.
Thanks for anyone who helps.
Edited on 13 November 2013 - 10:33 PM
ElvishJerricco #2
Posted 13 November 2013 - 06:02 PM
This isn't how Lua works. math.random just returns a single random number, and the myTable[1-5] won't even do remotely what you were hoping for a number of reasons.


local myTable = {}
for i=1,5 do
    myTable[i] = math.random()
end
Edited on 13 November 2013 - 05:02 PM
Agoldfish #3
Posted 13 November 2013 - 06:38 PM
I still do not understand.

local weatherTable = {66, 43, 90, 21}
local randomWeather = math.random()
--Test
print"Another beautiful day here at Presque Isle Downs!"
print"The weather today is ..."
for i=1,5 do
  weatherTable[i] = math.random()
  end
 
Here is the code I have, with your idea in there. Can you explain it with this?
MysticT #4
Posted 13 November 2013 - 07:36 PM
I guess you want a random value from the table. You need to use math.random to get a random index like this:

local weatherTable = { 66, 43, 90, 21 }
local randomWeather = weatherTable[math.random(1, #weatherTable)]
print(randomWeather)
What it does is generate a random number between 1 and the table size, so you can use it to index the table.
Kingdaro #5
Posted 13 November 2013 - 07:38 PM
What you'll want to do is make a new table, then randomly throw the contents of the first into the second using table.insert.

local weatherTable = {66, 43, 90, 21}

function shuffle(tab)
  local new = {}
  for i=1, #tab do
    table.insert(new, math.random(#new), tab[i])
  end
  return new
end

local randomized = shuffle(weatherTable)
Edited on 13 November 2013 - 06:39 PM
theoriginalbit #6
Posted 13 November 2013 - 07:40 PM
Yeh ok so Elvish's code is a little off… here is a better example (similar to MysticT's)


local myTable = {12, 45, 76, 23, 68, 34}

local randNum = math.random(#myTable) --# the same as math.random(1, #myTable)

print(myTable[randNum])

The reason your first method doesn't work is because math.random wants numbers, a table is not a number.
The reason your second method doesn't work is because it first calculates the math 1-5 which is -4 and there is not entry in the table at the index -4
The reason that Elvish's doesn't work is, well, lots of reasons, basically its just not what you want/need.
The difference between MysticT's and mine is that mine does not have the non-required first argument of 1 in the math.random, when this argument is not supplied 1 is assumed.

Now how the code example I provided works is that math.random is told to supply you with a random number between 1 and the amount of values in the table. This can then be used as it is a valid index for that table.

There is one time however where the above code example would fail, and that's when you have a table like so

local myTable = {1, 2, 3, [5] = 5, [6] = 6}
and the reason this fails is that it is non-sequential, there is no element in the 4th index, thus meaning that the # operator will tell you that there's only 3 elements, instead of 5… Obviously there will also be a problem with key/value pairs such as ["foo"] = 7. A solution to the above problem would be as follows

function table.random( tbl )
  local keys = {} --# lets make a copy of all the keys in the table
  for k in pairs( tbl ) do --# we have to use pairs as ipairs will have the same problem as # and stop when it hits the end of a sequential index
	if type(k) == "number" then --# lets only care about numbers, you can remove this if you also want to include the entries such as ["foo"] = "bar"
	  table.insert(keys, k) --# put the key into the table
	end
  end
  --# now we have a table containing all the index keys, lets pick a random key from that table
  local randIndex = math.random(#keys)
  local randKey = keys[randIndex] --# this is now the key for a random entry that's in our original table
  return tbl[randKey] --# returning the value from the original table using the key that we just randomly picked
end

As you can see the above code example is much more complicated, but it allows us to work with any table that has number values (and with slight modification any value) and return it, no matter the order or index of the index/key.
Edited on 13 November 2013 - 06:43 PM
Agoldfish #7
Posted 13 November 2013 - 07:59 PM
-snip-
Thank you! Not just you, to everyone who posted too!