Handling multiple matches for a table column value

Hi All,

In the Inform7 docs (WI 16. Tables) I find the following options for choosing a table row:

[ choose a/the/-- row (number) in/from (table name) ]
choose row 1 from the Table of Recent Monarchs;

[ choose a/the/-- row with (table column) of (value) in/from (table name) ]
choose row with a name of "Victoria" in the Table of Recent Monarchs;

So I either need to know the index of the row, OR some value for the given table column which must be known to exist.

Now I wonder: what would be the recommended way of handling multiple rows with the same table column value? The second statement will choose the first row which matches, but is there some way to get the NEXT match (if there is one)? I should mention that the column I am looking for is sorted, so the NEXT entry would be the one immediately following the current entry.

1 Like

I’ll let the ‘big guns’ give a good answer but my bad answer is to include a ‘key’ column which just starts at 1 and goes up (if you’re building it by hand, you can just do it manually, or if sorting you can run a ‘repeat through the table and change the key to current’ loop, incremementing current each time).

Then you can just say something like ‘let currentnum be key entry. Let nextnum be currentnum plus 1. Choose row with a key of nextnum in the table of blah’.

The usual way to do it is an explicit loop.

repeat through the Table of Monarchs:
    if the name entry is "Victoria":
        [do something with each relevant row]
1 Like

With these, a separate key index can be avoided:

to decide what table name is the current-table: (- ct_0 -).
to decide what number is the current-row-index: (- ct_1 -). [ suitable for use with choose row number X]
2 Likes

It’s not built-in, but

To choose the next row:
	(- {-my:ct_1}++; -).
2 Likes

I suppose if I would use that I would need some sentinel value to ensure the last bunch of entries does not run off the table…

There really oughta be a way to do this. So…

lab is a room.

Table of bad ideas
t-num   t-text
4   "this"
5   "hc"
4   "is"
7   "hhhh"
4   "a"
4   "success"

when play begins:
  choose row 1 in table of bad ideas; [ satisfy compiler ]
  repeat through table of bad ideas for t-num of 4 begin;
    say "[current-row-index] [t-text entry]!";
  end repeat;

to decide what number is the current-row-index: (- ct_1 -).

Include (-
[ TableRowEqual t col v row lookup_col i j f;
    if (col >= 100) col=TableFindCol(t, col, true);
    lookup_col = t-->col;
    j = lookup_col-->0 - COL_HSIZE;
    f=0;
    if (((t-->col)-->1) & TB_COLUMN_TOPIC) f=1;
    else if (((t-->col)-->1) & TB_COLUMN_ALLOCATED) f=2;
    j = (t-->col)-->(row+COL_HSIZE);
    switch (f) {
            1: if ((j)(v/100, v%100) ~= GPR_FAIL) return row;
            2: if (BlkValueCompare(j, v) == 0) return row;
            default: if (j == v) return row;
    }
    return 0;
];
-)

To repeat through (t - table name) with/for (col - K valued table column) of (v - value of kind K) begin -- end loop: (-
  @push ct_0; @push ct_1;
  {-my:ct_1} = 1;
  for ({-my:ct_1} = 1 : {-my:ct_1} <= TableRows({t}) : {-my:ct_1}++ )
  if (TableRowEqual({t}, {col}, {v}, {-my:ct_1})) {-block}
  @pull ct_1; @pull ct_0;
-).

Note that the compiler itself balks at a use of (column name) entry in a code block without anything that it recognizes as choosing a row, hence the seemingly gratuitous choose row before the repeat block.

2 Likes

As usual Zed, you amaze me with the code you create. I may be mistaken, but if all we want is to iterate through all rows given a certain condition, I can get the same result with this:

Am I forgetting something?

1 Like

Only my propensity for needlessly complicating things… :grinning:

1 Like