The latest round of Technology Refreshes, IBM i 7.4 TR5 and 7.3 TR11, brought in three new additions to the RPG language. I thought I would start with two new Built in Functions, BiFs, that return the greatest or lowest value from an array.
The two new BiFs, %MAXARRAY and %MINARRAY, have the same syntax:
%MAXARRAY(array-name : start-position : number-of-elements) %MINARRAY(array-name : start-position : number-of-elements) |
- array-name: Name of array or data structure array.
- start-position: The element to start the search from. Optional parameter.
- number-of-elements: Number of elements to search. Optional parameter.
Let me jump straight into some examples. Here is a program I wrote to illustrate how these BiFs work.
01 **free 02 dcl-s Array1 char(6) dim(10) ; 03 dcl-s Var1 char(6) ; 04 dcl-s Nbr1 uns(5) ; 05 dcl-s Empty uns(5) ; 06 Array1 = %list('782199':'563302':'676149':'836068':'489908': '828784':'221220') ; 07 Nbr1 = %maxarr(Array1) ; 08 dsply ('Array1 Nbr1 = ' + %char(Nbr1)) ; 09 Var1 = Array1(%maxarr(Array1)) ; 10 dsply ('Array1 Var1 = ' + Var1) ; 11 dsply ('Array1 Min value = ' + Array1(%minarr(Array1)) ) ; 12 Empty = %lookup(' ':Array1) ; 13 dsply ('Array1 Min value = ' + Array1(%minarr(Array1:1:(Empty - 1))) ) ; |
Line 2: The array I have defined here is very simple. Each element is six characters long, and there are ten elements.
Lines 3 – 5: Various variables defined that I will be using later in this program.
Line 6: The %LIST BiF is one of my favorite recent additions to RPG. I am loading the array with this one RPG statement. I am only loading seven of the possible ten elements. In debug I can see how the array is loaded.
> EVAL array1 ARRAY1(1) = '782199' ARRAY1(2) = '563302' ARRAY1(3) = '676149' ARRAY1(4) = '836068' ARRAY1(5) = '489908' ARRAY1(6) = '828784' ARRAY1(7) = '221220' ARRAY1(8) = ' ' ARRAY1(9) = ' ' ARRAY1(10) = ' ' |
Line 7: The maximum value BiF in its simplest form. Here it will return the array element where the greatest value in the array is.
Line 8: I am using the Display operation code, DSPLY, to show the element number.
DSPLY Array1 Nbr1 = 4 |
Line 9: This statement uses the array element retrieved by the %MAXARR BiF to be the element number for the array to give me the value of that position in the array.
Line 10: It is displayed thus:
DSPLY Array1 Var1 = 836068 |
Line 11: Now for the opposite BiF %MINARRAY. The result is:
DSPLY Array1 Min value = |
As I am only using seven of the ten elements in the array %MINARRAY has return blank from the first unused element.
Line 12: To overcome this I need to establish where the first blank element is in the array. I can use %LOOKUP to return the element number of the first blank element.
Line 13: Now I can use the %MINARRAY with the optional two parameters. I want to start searching at the first element of the array, and stop at the element that is one less than the first blank element. The results show:
DSPLY Array1 Min value = 221220 |
For a data structure array the syntax is slightly different:
%MAXARRAY(array-name(*).data-structure-subfield) %MINARRAY(array-name(*).data-structure-subfield) |
- array-name: Data structure array name. Must be followed by (*) to show that the entire data structure array will be used.
- data-structure-subfield: Name of the data structure subfield to be used
Onto my second example program:
01 **free 02 dcl-ds Array2 dim(10) qualified ; 03 Nbr char(6) ; 04 Char char(10) ; 05 end-ds ; 06 dcl-s Nbr1 uns(5) ; 07 Nbr1 = %maxarr(Array2(*).Nbr) ; 08 dsply ('Array2 Max elem = ' + %char(Nbr1)) ; 09 dsply ('Array2 Max value = ' + Array2(Nbr1).Nbr) ; 10 dsply ('Array2 Nbr Min value = ' + Array2(%minarr(Array2(*).Nbr)).Nbr) ; 11 dsply ('Array2 Nbr Min elem = ' + %char(%minarr(Array2(*).Nbr))) ; 12 dsply ('Array2 Char Min value = ' + Array2(%minarr(Array2(*).Char)).Char) ; 13 dsply ('Array2 Char Max value = ' + Array2(%maxarr(Array2(*).Char)).Char) ; |
Lines 2 – 5: The definition for my data structure array. It contains two sub fields. And the array has ten elements.
I have not shown the code to load the data structure array. When it is loaded it contains:
> EVAL array2 ARRAY2.NBR(1) = '463321' ARRAY2.CHAR(1) = 'First ' ARRAY2.NBR(2) = '236524' ARRAY2.CHAR(2) = 'Second ' ARRAY2.NBR(3) = '125098' ARRAY2.CHAR(3) = 'Third ' ARRAY2.NBR(4) = '473775' ARRAY2.CHAR(4) = 'Fourth ' ARRAY2.NBR(5) = '366479' ARRAY2.CHAR(5) = 'Fifth ' ARRAY2.NBR(6) = '573670' ARRAY2.CHAR(6) = 'Sixth ' ARRAY2.NBR(7) = '392723' ARRAY2.CHAR(7) = 'Seventh ' ARRAY2.NBR(8) = '374816' ARRAY2.CHAR(8) = 'Eighth ' ARRAY2.NBR(9) = '000001' ARRAY2.CHAR(9) = 'Ninth ' ARRAY2.NBR(10) = '000001' ARRAY2.CHAR(10) = 'Tenth ' |
Line 6: There is only one additional variable I will be using in this program.
Lines 7 – 9: This is the simplest way to get the array element and value that has the maximum value. Here I want to get the maximum value from the Nbr subfield. This displays:
DSPLY Array2 Max elem = 6 DSPLY Array2 Max value = 573670 |
Lines 10 and 11: Show the minimum value in the data structure array Nbr sub field.
DSPLY Array2 Nbr Min value = 000001 DSPLY Array2 Nbr Min elem = 9 |
Both BiFs will return the first element where the maximum or minimum value is found. As the data structure array subfield has two elements that contain the value '000001' the first one is returned.
Lines 12 and 13: Let me do the same for the other subfield Char.
DSPLY Array2 Char Min value = Eighth DSPLY Array2 Char Max value = Third |
This pair BiFs are useful addition to RPG.
You can learn more about the %MAXARRAY and %MINARRAY RPG Built in Functions from the IBM website here.
This article was written for IBM i 7.4 TR5 and 7.3 TR11.
What unnecessarily confused me was that you say that these functions return a value, which is, thanks to IBM (So these functions are far more usable), not the case, they return the index, which is clear when one reaches the source code.
ReplyDeleteI would have found something like "return the index of the array element containing the min/max value" much clearer, although it's way longer.
Thank you!
More and more functions and improvements are added (regularly) to RPG (and DB2 and OS400), increasing the value of modernization in-situ!
ReplyDeleteAwesome IBMi.
Yeyyy, this is a really handy functionality. Thanks for sharing.
ReplyDeleteSimon, these BIF”s will be very useful. Thanks for sharing.. this is my first time seeing these, wasn’t working on those types of problems for a long time..
ReplyDeleteGreat info thanks
ReplyDelete