Guidance
指路人
g.yi.org
Guidance Forums / Reginald Rexx / Array key search

Register 
注册
Search 搜索
首页 
Home Home
Software
Upload

  
Forum List • Thread List • Reply • Refresh • New Topic • Search • Previous • Next First 1 Last
Message1. Array key search
#1337
Posted by: guidance 2002-11-11 13:55:25
If I use a 2 dimensional array to store a data table, I want the first tail name as its key, i.e.:
key1       key2      key3
---------------------------
data11   data12   data13
data21   data22   data23

data.key1.1='data11'
data.key1.2='data21'
data.key2.1='data12'
data.key2.2='data22'
data.key3.1='data13'
data.key3.2='data23'
Now, if I want to search and delete the whole column of key2, what's the easiest, most efficient way?
Message2. Re: Array key search
#1338
Posted by: 2002-11-12 14:05:56
I think that your best bet would be to use a separate 1-dimensional array for each column. Form a stem name that tells you the column as so:
column1.1 = 'data11'
column1.2 = 'data21'
column2.1 = 'data12'
column2.2 = 'data22'
column3.1 = 'data13'
column3.2 = 'data23'
That way, if you want to delete column2, all you need do is:
DROP column2.
And if you want to enumerate all of the items under column2, you can use a DO OVER loop.

DO OVER is a way to loop over all variables that use a certain stem, without knowing exactly how many, and what, tail names use that stem. For example, if you want to find out the names of all variables that use the stem column2., you can do:
DO i OVER column2.
   SAY column2.i
END
Each time around the loop, i will be set to the next tail name that uses "column2.". For example, let's say you have the following:
mystem.name = "Jeff"
mystem.1 = 100
mystem.first.second = "Some string"
DO i OVER mystem.
   SAY mystem.i
END
The first time through the DO OVER loop, the variable i is set to the value "name". That's because name is the first tail that uses MyStem as its stem. So you actually SAY the value of MyStem.name and "Jeff" gets displayed. The second time through the DO OVER loop i is set to the value "1". That's because 1 is the second tail that uses MyStem as its stem. So you actually SAY the value of MyStem.1 and "100" gets displayed. The third time through the DO OVER loop, the variable i is set to the value "first.second". That's because first.second is the third tail that uses MyStem as its stem. So you actually SAY the value of MyStem.first.second and "Some string" gets displayed. Then the DO OVER loop ends because there are no more tail names that use MyStem.
In other words, DO OVER can be used to enumerate all of the tails that use a given stem, and thereby access the values of each of those variables.

The only caveat is that there is no guaranteed order to enumerating the tails. For example, they are not enumerated in alphabetical order. So, if you need a specific order, then this is not going to work for you.
Message3. DO OVER limitations
#1339
Posted by: guidance 2002-11-13 10:46:21
Does DO OVER work only for 1-dimensional arrays? If I use my above array, and do:
DO i OVER data.
   SAY data.i
END
It gives me all 9 elements.

But a 1-dimensional array can't solve my problem. I use a variable to hold the total count of columns. And I want a 2-dimensional array with descriptive names (ie, not numbers) as subscripts (tails), such as: key1, key2, anotherKey, etc. I don't want to use numbers for tails.
Message4. DO OVER, DROP, assignment limitations
#1340
Posted by: 2002-11-13 14:49:37
For most interpreters, DO OVER works only with one-dimensional arrays because that's the way that Object REXX works (and IBM's Object REXX is where the DO OVER feature first appeared). Reginald's DO OVER will work with compound variables. (And many interpreters do not even support DO OVER).

But note also that
DROP data.key2.
won't DROP all compound variables that use data.key2. as their root.

Neither will
data.key2. = "Empty"
Initialize all compound variables that use data.key2. as their root.

These DROP and assignment "shortcuts" work only with one-dimensional arrays.
Message5. Re: DO OVER, DROP, assignment limitations
#1341
Posted by: guidance 2002-11-13 14:59:04
Yes, I noticed the limitations with array DROP and initialization.

Can these be changed?
Message6. Re: Array key search
#1342
Posted by: 2002-11-13 17:39:30
I don't know as if I'd want to change the way that DROP and variable assignment work since those are well-standardized behaviors among all REXX interpreters. But DO OVER is not really a REXX standard. So, Reginald supports DO OVER on compound variables (which Object REXX doesn't).

So Reginald allows DO OVER to work with two (or more) dimensional arrays. You can do:
DO i OVER data.key2.
   SAY data.key2.i
END
Therefore, you can simulate the DROP "shortcut" yourself as so:
/* DROP all variables that use data.key2. as their root */
DO i OVER data.key2.
   DROP data.key2.i
END
There's not a way to perfectly simulate the assignment shortcut. You can do:
/* Assign "empty" to all variables that use data.key2. as their root */
DO i OVER data.key2.
   data.key2.i = 'empty'
END
But one difference here is that variables which haven't yet been given a value still default to their name upper-cased. So now you have different values for cells which haven't yet been created, and ones which are marked as "empty". That may not be a problem for you. If it is, there is something you can do.

If you need to mark a "cell" as "empty", I think that you should just DROP it. Then you can always use SYMBOL() to test if the cell is empty, and use INTERPRET if you have to create the variable name on-the-fly.
/* Test if the first 4 columns of row one are empty */
DO i = 1 TO 4
   INTERPRET "test = SYMBOL('data.key2." || i || "')"
   IF test == 'VAR' THEN SAY "Cell is not empty"
   ELSE SAY "Cell is empty"
END

/* Test which cells are empty in the first row. totalRows is how many rows there are */
DO i = 1 TO totalrows
   INTERPRET "test = SYMBOL('data.key" || i || ".1')"
   IF test == 'VAR' THEN SAY "Cell is not empty"
   ELSE SAY "Cell is empty"
END
The advantage of the above is that, cells which are not yet created are the same as cells which are DROP'ed -- ie, "empty". So you don't really need any "default value" to mark a cell as empty. It is automatically empty if you haven't yet assigned it a value. Otherwise, when you DROP it, it becomes empty again.
Message7. Re: Array key search
#1347
Posted by: guidance 2002-11-14 10:32:17
Still not a very useful DO OVER:
data.key1.1='data11'
data.key1.2='data21'
data.key2.1='data12'
data.key2.2='data22'
data.key3.1='data13'
data.key3.2='data23'
DO i OVER data.
 DO j OVER i. /* or: do j over data.i. ? */
  SAY i j data.i.j
 END
END
In this situation, I want to enumerate the subkeys of i., which should be key1, key2, key3, etc., but the above code displays nothing at all.
Message8. Re: Array key search
#1768
Posted by: Jeff Glatt 2003-05-05 15:30:16
The reason why nothing is being displayed is because there is no stem named i. used in your script. It has no existing tails. So the inside loop (with the SAY instruction) never gets executed at all.

I don't have any clue what you're really trying to do. I assume that you're trying to make some sort of 2-dimensional "grid", but I have no idea what the specifications are. I get the impression that it has a variable number of rows, as well as a variable number of columns, but I'm guessing here. And I think that some of the "cells" can be empty, but again, I'm guessing here. And I think that there are a large number of cells, and therefore there could be a large number of empty ones. So maybe you're trying to use DO OVER to enumerate only those cells that aren't empty (ie, ones that have been assigned a value) in the hopes of saving yourself the trouble of having to maintain a count of how many cells (columns) are in each row, or maybe how many rows there are. I'm guessing here. I don't know as if you're maintaining counts of how many columns and rows there are. And maybe you're even hoping to avoid going through every possible cell to check if it's "empty" or has data when you loop through the data. Again, I'm guessing because you haven't said what it is you're trying to accomplish with DO OVER. (You do realize that if you need to traverse a row or column in order, DO OVER will never work for you? DO OVER will enumerate variables in no particular order. Again, I don't know as if this is needed, because you haven't said).
/* Here's our array */
data.1.1='data11'
data.1.2='data21'
data.2.1='data12'
data.2.2='data22'
data.3.1='data13'
data.3.2='data23'

/* Get the column number to enumerate */
SAY "Which column would you like to list (1, 2, or 3)?"
PULL col

/* Enumerate the values of the cells in that column */
DO i OVER data.col.
   SAY data.col.i
END

/* ================================= */
/* Get the row number to enumerate */
SAY "Which row would you like to list (1, 2, or 3)?"
PULL row

/* Form the tail name */
row = '.' || row
LENGTH = LENGTH(row)

/* We have to go through all items in our grid */
DO i OVER data.

   /* We have another cell. See if this is in the row we desire. We can
    * check this by inspecting the value of "i" (ie, the variable name).
    * If it's the row we want, then its last tail name will match "row"
    */
   IF RIGHT(i, length) = row THEN SAY data.i

END

/* If we know how many columns and rows we have, we can
 * dispense with DO OVER, and enumerate the cells ourselves.
 * The advantage here is that they are listed in a specific
 * order.
 */
numofrows = 3
numofcols = 2

DO i = 1 TO numofcols

   DO j = 1 TO numofrows

      CALL CHAROUT(,data.j.i)
      CALL CHAROUT(,"   ")

   END /* numofrows */

   CALL CHAROUT(,"0D0A"x)

END /* numofcols */

EXIT
Message9. Re: Array key search
#1769
Posted by: Jeff Glatt 2003-05-05 15:31:41
Guidance writes:

I want a 2-dimensional array with descriptive names (ie, not numbers) as subscripts (tails), such as: key1, key2, anotherKey, ...

My real task is to delete a certain column specified by its tail name, not index number. I'm trying to enumerate each element by traversing whole array.

I hope the first (outer) DO OVER can tell me all the first subscript (tail), and the second (inner) one tells the second one's, etc. I don't care about the order. Then I can compare the tail and decide to DROP it or not.
I suppose it's similiar to the "foreach" statement in PHP or VB.
Message10. Re: Array key search
#1770
Posted by: Jeff Glatt 2003-05-05 15:37:17
No problem.
/* Here's our array */
data.key1.1='data11'
data.key1.2='data21'
data.key2.1='data12'
data.key2.2='data22'
data.key3.1='data13'
data.key3.2='data23'
/* Get the column number to enumerate */
again:
SAY "Which column would you like to list (1, 2, or 3)?"
PULL col
IF DATATYPE(col, 'W') == 1 THEN DO
   SAY "You didn't follow the instructions. I said to enter a number."
   SIGNAL again
END
col = "KEY" || col
/* Enumerate the values of the cells in that column */
DO i OVER data.col.
   SAY data.col.i
END
EXIT

One note on the above: Tail names are case-sensitive when not quoted. So that is why I uppercase the variable name KEY when I *did* put it in quotes:
col = "KEY" || col
I want to make sure that I reference "KEY" (not "Key" nor "key", etc) because my reference needs to be to the same Key variable used in other instructions such as:
data.key1.1 = 'data11'
REXX automatically uppercases any variable name not in quotes, so the above line is actually translated by REXX into:
data.key1.1 = 'data11'
And although data.KEY1 may be the same variable as DATA.KEY1 (ie, the stem part of any variable is always case-insensitive), DATA.KEY1 is not the same as DATA.Key1 (ie, the tail names are case sensitive).
Message11. Re: Array key search
#1771
Posted by: Jeff Glatt 2003-05-05 15:40:44
Guidance writes:

If I do this:
DO i OVER data.
   PARSE VAR i subdata '.'
   DO j OVER data.subdata.
      SAY data.subdata.j
   END
END
The first DO OVER enumerates all 6 elements, not limited within first tail only, thus I got total 12 SAYs.

Your example works. But I want to use an arbitrary name for my tails (not a specific format to every key name). My above example displays all 12 variables that reference data. as their stem. How can instead just reference the variables using one of the key tails?
Message12. Re: Array key search
#1772
Posted by: Jeff Glatt 2003-05-05 15:41:16
Just use the example I showed you, except instead of getting the "name" from the user (which I did just to show you how to dynamically, and therefore, arbitrarily get some variable name), assign the desired tail name yourself. The only thing you have to be careful about is to make sure that you upper case that column (tail) name (which you can do with the TRANSLATE function if necessary).
data.key1.1='data11'
data.key1.2='data21'
data.keygg2.1='data12'
data.keygg2.2='data22'
data.keytat3.1='data13'
data.keytat3.2='data23'

/* Let's say we want to enumerate the column named 'keygg2" */
col = "KEYGG2"

/* Enumerate the values of the cells in that column */
DO i OVER data.col.
   SAY data.col.i
END
EXIT
Message13. Re: Array key search
#1773
Posted by: Jeff Glatt 2003-05-05 15:42:18
Guidance writes:

I would like to give a PHP code for illustration:
$data['key1'][1]='data11';
$data['key1'][2]='data21';
$data['keygg2'][1]='data12';
$data['keygg2'][2]='data22';
$data['keytat3'][1]='data13';
$data['keytat3'][2]='data23';

foreach ($data as $i) // here $i will be a one-dim sub-array WITH 2 elements inside
{
   foreach ($i as $j)
   {
      echo $j;
   }
}
Should output these 6 elements.

If I want to delete column keygg2:
foreach ($data as $key => $i)
{
   IF ($key=='keygg2') unset($data[$key]);
}
If want to delete row 2:
foreach ($data as $key1 => $i)
{
   foreach ($i as $key2 => $j)
   {
      IF ($key2==2) unset($data[$key1][$key2]);
   }
}
Seems hard to write the equivalent in Rexx.
Message14. Re: Array key search
#1774
Posted by: Jeff Glatt 2003-05-05 15:42:56
Here it is:
data.key1.1      = 'data11'
data.key1.2      = 'data21'
data.keygg2.1  = 'data12'
data.keygg2.2  = 'data22'
data.keytat3.1 = 'data13'
data.keytat3.2 = 'data23'

/* Delete column "keygg2" */
colname = "KEYGG2"
DO i OVER data.colname.
   DROP data.colname.i
END

data.key1.1      = 'data11'
data.key1.2    = 'data21'
data.keygg2.1  = 'data12'
data.keygg2.2  = 'data22'
data.keytat3.1 = 'data13'
data.keytat3.2 = 'data23'

/* Delete row "2" */
rowname = 2
DO i OVER data.
   PARSE VAR i col '.' row '.' .
   IF row == rowname THEN DROP data.i
END


That's pretty easy to me. And note that you can use names for your rows as well as columns. For example, you can have a row named 'MyRow' as so:
data.key1.1       = 'data11'
data.key1.myrow    = 'data21'
data.keygg2.1       = 'data12'
data.keygg2.myrow  = 'data22'
data.keytat3.1      = 'data13'
data.keytat3.myrow = 'data23'

/* Delete row "MyRow" */
DO i OVER data.
   PARSE VAR i col '.' row '.' .
   IF row == myrow THEN DROP data.i
END
Forum List • Thread List • Reply • Refresh • New Topic • Search • Previous • Next First 1 Last
掌柜推荐
 
 
 
 
 
 
 
 
 
 
 
 
© Wed 2024-4-24  Guidance Laboratory Inc.
Email:webmaster1g.yi.org Hits:0