Filtering and picking a random row from a table

So the manual says you can do something like this:

choose a random row in my table

My question is, say my table has a column called foo, which contains a number. How can I select a random row in the table with a specified value of foo. I.e. something like this:

chose a random row in my table where foo is 1

(which obviously doesn’t compile, or I wouldn’t be asking the question).

So any ideas on how to pick a random row, but with some precondition on which row you pick?

Try this:

Sort the table of whatever in random order; If the interesting foo is a foo listed in the table of whatever: (the row is chosen within this scope) Otherwise: (the interesting foo does not occur at all)

Obviously, this has the side-effect of reordering the table.

So, if I understand this correct, that’ll pick the first row with “interesting foo”, but because we shuffled the list first, it won’t be the same one every time. Nice! Thanks.

On the other hand, it doesn’t seem terribly efficient to shuffle a table and then search it for a value, but I guess since the table is likely to be small, it’s not too much of a big deal.

I guess the final option, although it’s a bit of a pain to code, is to keep a separate table for each value of foo and just switch to a different table based on foo (maybe even have another table to act as an index).

I.e. something like this:

table of index
foo   table
1      foo-table-1
2      foo-table-2

table of foo-table-1
bar
"blah, blah, blah"
"yadda, yadda, yadda"

table of foo-table-2
bar
"etc, etc, etc"

If your randomly selected values are strings, it might be neater to just have one string per foo, but have that string be one with lots of “[one of]…[or]…[or]…[in random order]”.

The more efficient solution is probably to have two tables, A and B, and use the following algorithm:

  • Empty B.
  • Repeat through A; if value of the column is foo, copy line to B.
  • Choose a random row from B.

This way you won’t have to do any sorting, and you will not change the order of A (if that is important to you).

You can do the same thing without an extra table, also in O(N) time:

  1. Count the number of matching rows in your table.

  2. Pick a random number from 1 to the count.

  3. Loop through your table again, until the count matches the random number you picked.

It’s not as Informish, but it’s still relatively quick and doesn’t use much memory.

But in practical terms, sorting in Inform is very fast. After all, how often do you have more than a couple dozen rows in your table? I wouldn’t expect to see a noticeable difference in speed. If anyone decides to benchmark it, please let me know the results!