Currently I have been making by without using any data structures in
my program but now I have a need for a dynamic array.
For instance:
I'm collecting values from a file such as:
String length of 0000006A000005F2 is 16
1.3.18.0.0.3330->internetRouter
String length of 0000006B0000084C is 16
1.3.18.0.0.6464->aggregateSystem
String length of 0000007B0000084D is 16
Object name: interfaceLink
String length of 0000006B0000084C is 16
1.3.18.0.0.6464->aggregateSystem
String length of 00000011000005E1 is 16
Object name: Non_SNA_Domain_Class
as you can see, there are 2 aggregatedSysm or 1.3.18.0.0.6464
I only want 1 to be saved for later processing.
For instance:
I want to store:
array.1 = "1.3.18.0.0.3330"
array.2 = "1.3.18.0.0.6464"
array.3 = "Non_SNA_Domain_Class"
but if the array element is already in there, I don't want to re-add
it...
so if I'm going to insert the following value: 1.3.18.0.0.6464 into
the array,
and you can see, 1.3.18.0.0.6464 is already in the array, at location:
array.2.
Then don't add it.
The problem is, I don't know how many of these "objects" I'm going to
be storing in this array.
There could be 3, or there could be 1000 within a file, infact there
probably will be.
but I don't want to create an massive array like
array.0 = 30000
and Hope it doesn't go over 30,000 elements, it also would be a waste
of space.
I want the array to get bigger as eleemnts are added.
Any ideas?
Thanks!
--
IBM Intern
array.0 = 30000
All it does is assign a single compound variable to the number 30000.
It doesn't allocate any storage behind any of the elements from array.1
to array.30000 until you explicitly assign something to those elements.
btw, if you ever make the switch to ooRexx, the SET class will handle
all of the duplicate elimination for you.
Rick
> as you can see, there are 2 aggregatedSysm or 1.3.18.0.0.6464
> I only want 1 to be saved for later processing.
>
> For instance:
> I want to store:
> array.1 = "1.3.18.0.0.3330"
> array.2 = "1.3.18.0.0.6464"
> array.3 = "Non_SNA_Domain_Class"
>
> but if the array element is already in there, I don't want to re-add
> it...
> so if I'm going to insert the following value: 1.3.18.0.0.6464 into
> the array,
> and you can see, 1.3.18.0.0.6464 is already in the array, at location:
> array.2.
> Then don't add it.
>
> The problem is, I don't know how many of these "objects" I'm going to
> be storing in this array.
> There could be 3, or there could be 1000 within a file, infact there
> probably will be.
>
> but I don't want to create an massive array like
> array.0 = 30000
> and Hope it doesn't go over 30,000 elements, it also would be a waste
> of space.
>
> I want the array to get bigger as eleemnts are added.
>
> Any ideas?
How about:
------------------- cut here -----------------
array. = "0" /* default value for stem */
/* define a string with (duplicate) words */
string="1.3.18.0.0.3330 1.3.18.0.0.6464" ,
"Non_SNA_Domain_Class 1.3.18.0.0.6464 "
do i=1 to words(string) /* loop over words */
w=word(string,i) /* extract word */
if array.w=0 then /* not yet in stem? */
do
array.w=1 /* now we have it! */
i=array.0+1 /* increase counter */
array.i=w /* store value */
array.0=i /* store counter */
end
end
say "We have" array.0 "unique entries:"
do i=1 to array.0
say " #"i":" array.i
end
------------------- cut here -----------------
HTH,
---rony
In the example you've given there's no obvious reason to use a stem variable
at all. You could just start off with:
things = ""
and later
if wordpos(element,things) = 0 then things = things element
which builds a list of unique elements. Instead of accessing the n'th
element of a stem, as array.n, you'd use word(things,n). Whether that is
sensible is another issue altogether.
Or you could keep a list of values as suggested above, but if you need
arrays of values elsewhere, just store the word-numbers elsewhere.
--
Jeremy C B Nicoll - my opinions are my own.
Hi Rony,
Thanks for the reply.
I had some questions on your code:
Do I create a string and every time I want a parsed value from the
file, concatenate it to the string?
is this possible to concatinate a string and leave a space in it?
like say I have the following:
collectedData = ""
objectNameLine = LineIn(inputFile)
Parse Value objectNameLine with target
target = Strip(target,"Both")
if(isOSI(target) == 1) then
do
englishName = CCNVOSI(target)
say target || "->" || englishName
collectedData = collectedData || " " || englishName
end
else
say "Object name: " || target
collectedData = collectedData || " " || target
Is this how you would generate that string with:
string="1.3.18.0.0.3330 1.3.18.0.0.6464" ,
"Non_SNA_Domain_Class 1.3.18.0.0.6464 "
Then I could use:
do i=1 to words(string) /* loop over words */
w=word(string,i) /* extract word */
if array.w=0 then /* not yet in stem? */
do
array.w=1 /* now we have it! */
i=array.0+1 /* increase counter */
array.i=w /* store value */
array.0=i /* store counter */
end
end
say "We have" array.0 "unique entries:"
do i=1 to array.0
say " #"i":" array.i
end
I'm not following this part:
w=word(string,i) /* extract word */
if array.w=0 then /* not yet in stem? */
I understand w = word(string,i) this is assigning w the "word" like w
= word(string,2) would be 1.3.18.0.0.6464
but then you check if array.w=0 then
whats this checking? if array.w = 0, meaning if the array is
empty?
Hows does that chunk of code know if the value is in there or not
already so there aren't duplicated items?
Thanks for the help!
Also thanks for ur tips Nicoll
You are already using this:
> say "We have" array.0 "unique entries:"
And:
SAY "Try " "this"
SAY "Try" "this"
> objectNameLine = LineIn(inputFile)
> Parse Value objectNameLine with target
> target = Strip(target,"Both")
PARSE VALUE LineIn(inputFile) WITH target
target=Strip(target)
Or:
PARSE VALUE Strip(LineIn(inputFile)) WITH target
Or just:
target=Strip(LineIn(inputFile))
---
> say "Object name: " || target
Say "Object name:" target
> collectedData = collectedData || " " || target
collectedData=collectedData target
Just like:
> say "We have" array.0 "unique entries:"
---
Lesse, where to begin.
First of all, Rexx does not HAVE any arrays. What it has are compound
variables. Now, the interpreter will treat these as arrays for the
purpose of processing, but in reality, they are not. If you create an
array:
My_Array. = ''
Array_CNTR = 0
You can happily loop through with
Arrary_CNTR = Arrany_CNTR + 1
My_Array.Array_CNTR = Some_Junk
And add lines all day long. The ONLY limitation here is actually the
amount of storage your TSO session has, before Rexx pukes trying to
add rows.
Mickey
> Hi Rony,
>
> Thanks for the reply.
>
> I had some questions on your code:
>
> Do I create a string and every time I want a parsed value from the
> file, concatenate it to the string?
> is this possible to concatinate a string and leave a space in it?
Yes, as other posters mentioned.
In Rexx listing variables or strings with intervening blanks will concatenate all of them with *one*
blank. If you want two strings to be concatenated without an intervening blank, then you need to use
the concatenation operator, which is two bars (||); or, if one is a variable and the other a string,
then you could just write them next to each other without an intervening blank (that's then an
"abuttal" concatenation).
The Rexx interpreter conceptually does the following:
- it reads a line,
- it uppercases everything outside of quotes,
- it reduces multiple blanks between tokens to one blank,
- it interprets this new string
e.g.
say "Hi" there"this" || reverse( "is") "it!"
will get transformed to before interpretation:
SAY "Hi" THERE"this" || REVERSE( "is") "it!"
yielding (just copy and paste it into a rexxtry session to see for yourself):
Hi THEREthissi it!
If a variable in Rexx does not have a value, then the Rexx interpreter takes the name of a variable
as its value. As Rexx variables will never be enclosed in quotes, the variable's name is uppercased,
before its use.
... snip ...
> I'm not following this part:
> w=word(string,i) /* extract word */
> if array.w=0 then /* not yet in stem? */
>
> I understand w = word(string,i) this is assigning w the "word" like w
> = word(string,2) would be 1.3.18.0.0.6464
> but then you check if array.w=0 then
> whats this checking? if array.w = 0, meaning if the array is
> empty?
>
> Hows does that chunk of code know if the value is in there or not
> already so there aren't duplicated items?
A stem variable can have any string as an "index" value right after the first dot. (That string may
even contain dots itself, but also blanks, upper- and lowercase letters, nonprintable letters,
everything.)
The trick here is to use the string value as an index. One can determine whether it got already
used, if the programming convention is to set its value to something different of "0"
(alternatively, you could use the VAR()-BIF - built-in-function, e.g. VAR("stem.w") to determine
whether we have processed that entry already.
One is able to define a default value for stem variables. Every time one tries to access a stem
entry, and it does not exist, the default value is returned instead. (In the supplied example the
default value was "0".)
The other "trick" here is to use a programming convention with Rexx stems: use integer numbers from
1..n as index for stems and store the actual total number of entries with the index "0". This way
one can treat such a stem as an array, e.g.:
stem.0=0 /* stem has no entries */
stem.1="Nr. one"
stem.0=1 /* indicate stem has one entry */
stem.2="Nr. one"
stem.0=2 /* indicate stem has two entries */
do i=1 to stem.0 /* iterate over all entries */
say i":" stem.i
end
HTH,
---rony
with ooRexx you could solve your problem also differently, one possibility (as Rick mentioned) is to
use the "set" datatype (it removes duplicates):
----------------- cut here --------------------
/* one possible ooRexx solution in addition: */
string="1.3.18.0.0.3330 1.3.18.0.0.6464" ,
"Non_SNA_Domain_Class 1.3.18.0.0.6464 "
array=string~makeArray(" ") /* turn into an array of words*/
set =.set~new~union(array) /* use a set to remove dupes */
say "We have" set~items "unique entries:"
i=1 /* set start value for counter */
do word over set /* iterate over collected objects (words) */
say " #"i":" word
i=i+1 /* increase counter */
end
----------------- cut here --------------------
HTH,
---rony
as you were interested in sorting as well, in the next version of ooRexx you could easily sort the
set's content to get a sorted list of all unique words in the set:
rony wrote:
> Hi,
>
> with ooRexx you could solve your problem also differently, one possibility (as Rick mentioned) is to
> use the "set" datatype (it removes duplicates):
>
> ----------------- cut here --------------------
> /* one possible ooRexx solution in addition: */
> string="1.3.18.0.0.3330 1.3.18.0.0.6464" ,
> "Non_SNA_Domain_Class 1.3.18.0.0.6464 "
>
> array=string~makeArray(" ") /* turn into an array of words*/
> set =.set~new~union(array) /* use a set to remove dupes */
>
> say "We have" set~items "unique entries:"
> i=1 /* set start value for counter */
> do word over set /* iterate over collected objects (words) */
--> replace the above statement with the following to get a sorted list:
do word over set~allIndexes~sort
> say " #"i":" word
> i=i+1 /* increase counter */
> end
> ----------------- cut here --------------------
BTW, everyone who is interested could get at that developer version of this future version of ooRexx
by going to the following place:
<http://build.oorexx.org/builds/interpreter-3.x/>
The latest docs for this future version can be downloaded from:
<http://build.oorexx.org/builds/docs/>
Always pick the directory with the highest number (correpsonds to the svn revision number, i.e. the
higher the number, the newer the builds).
HTH,
---rony
Mike Cowlishaw introduced me to another way of abutting two variables,
using an intervening null string:
A = 'hippo'
B = 'potamus'
Say A''B /* hippopotamus */
I used this extensively until benchmarking showed that A || B was about
one microsecond faster on the processors I use (my PC, and my
departmental webserver) because internally it is one abuttal instead of two.
I also discovered that changing A''B to A||B reduced the severity of the
Segmentation Problems I encountered in IBM Object Rexx and early Open
Object REXX, but that's an entirely different topic.
My only real reason for preferring the A''B abuttal mechanism is that
the vertical bar (|) is in a slightly awkward position on my UK
keyboard, and I found using the non-shifted (') character easier to type.
Similarly, I adopted <> in preference to \= or even ャ= (on mainframes)
because it is significantly easier to type.
--
Steve Swift
http://www.swiftys.org.uk/swifty.html
http://www.ringers.org.uk