I wrote earlier about a new Built in Function, BiF, that makes it easier to concatenate variables or strings. Another addition to the RPG language in the fall Technology Refreshes, IBM i 7.5 TR1 and 7.4 TR7, is another BiF to concatenate elements from an array.
The syntax of %CONCATARR BiF is very similar to %CONCAT I wrote about before:
Result = %concatarr(<separator character(s)> : <array name>) ; |
Let me jump to my first example. This is the RPG code for the first part of my example program:
01 **free 02 dcl-s VarArray varchar(10) dim(*auto:100) ; 03 dcl-s NbrArray packed(5:2) dim(*auto:10) ; 04 dcl-s FixedArray char(10) dim(100) ; 05 dcl-s String char(100) ; 06 VarArray = %list('Amy' : 'Beth' : 'Carol' : 'Dawn' : 'Enid') ; 07 String = %concatarr(', ' : VarArray) ; |
Line 1: All my RPG code is now free (format).
Line 2: I am defining an array where its elements are variable character, VARCHAR. The *AUTO keyword denotes that it will be a variable length array, which will automatically extend when I add data to it, up to 100 elements.
Line 3: Another variable length array, but this one's elements are packed numeric.
Line 4: This is a more "traditional" array, fixed length character elements and 100 elements.
Line 5: This is the definition for the variable that will contain the results of the concatenation.
Line 6: I load the elements of the array using the %LIST BiF. As I am loading five values into the array, it will have five elements not 100.
Line 7: The %CONCATARR BiF concatenates the elements together and put the result in the variable String.
The result looks just the way I want it to:
> EVAL String STRING = ....5...10...15...20...25...30...35...40...45...50...55...60 1 'Amy, Beth, Carol, Dawn, Enid ' 61 ' ' |
Thanks to the variable length array that was simple. What about doing the same with the fixed sized array?
08 FixedArray = %list('Alan' : 'Ben' : 'Clint' : 'David' : 'Elvis') ; 09 String = %concatarr(', ' : FixedArray) ; |
Line 8: I load the first five elements using the %LIST BiF.
Line 9: Using the %CONCATARR with the fixed size array gives me the following result:
> EVAL String STRING = ....5...10...15...20...25...30...35...40...45...50...55...60 1 'Alan , Ben , Clint , David , Elvis , ' 61 ' , , , ' |
As the elements are all fixed character sized and there are 100 elements the result looks messy.
Fortunately I can use the %TRIMR BiF to remove the trailing blanks from all of the elements:
10 String = %concatarr(', ' : %trimr(FixedArray) ) ; |
The result looks better for the values in the first five elements.
> EVAL String STRING = ....5...10...15...20...25...30...35...40...45...50...55...60 1 'Alan, Ben, Clint, David, Elvis, , , , , , , , , , , , , , , ' 61 ', , , , , , , , , , , , , , , , , , , , ' |
I don't want the unused elements in my string. My solution may look complicated, but it is really not. I am just combining BiFs together in one statement.
I will need the following BiFs:
- %CONCATARR: You should know what that does by now
- %TRIMR: Remove trailing blanks from a string
- %SUBARR: Substring a number of elements from an array
- %LOOKUP: Find the first element in an array that is equal to test value
My statement looks like:
11 String = %concatarr(', ' : 12 %trimr(%subarr(FixedArray : 13 1 : 14 %lookup(' ':FixedArray:1) -1))) ; |
Line 11: Is already familiar.
Line 12: I have the %TRIMR to remove the trailing blanks from the %SUBARR that just extracts the used elements from the fixed array.
Line 13: The array substring starts at the first element.
Line 14: To determine the last used element I use the %LOOKUP. I am looking for a blank element, starting from the first position. When I find it I subtract one to get the last used element.
The result is exactly what I wanted:
> EVAL String STRING = ....5...10...15...20...25...30...35...40...45...50...55...60 1 'Alan, Ben, Clint, David, Elvis ' 61 ' ' |
If I had a random list of values that I wanted to concatenate in a sorted order I would need to use the SORTA operation code. I would do it like:
15 %elem(VarArray) = 0 ; 16 VarArray = %list('Zach' : 'Mike' : 'Xavier' : 'Will' : 'Jim') ; 17 sorta VarArray ; 18 String = %concatarr(', ' : VarArray) ; |
Line 15: I reset the number of elements in the variable length array to zero, as my new list may have more or less elements than what it contains now.
Line 16: I load the array using the %LIST BiF.
Line 17: I sort the array in the default, ascending, order.
Line 18: Then I concatenate the array into String.
The result is:
> EVAL String STRING = ....5...10...15...20...25...30. 1 'Jim, Mike, Will, Xavier, Zach |
My final example is with a numeric array, which is defined on line 3.
19 NbrArray = %list(5.03 : 3.12 : 8.97 : 7.31 : 15) ; 20 String = %concatarr(', ' : %char(NbrArray) ) ; |
Line 19: Using %LIST to load the values into the array.
Line 20: It is not possible to concatenate numbers, therefore, I need to convert the arrays elements to character using the %CHAR BiF.
The result is:
> EVAL String STRING = ....5...10...15...20...25...30...35...40...45...50...55...60 1 '5.03, 3.12, 8.97, 7.31, 15.00 ' 61 ' ' |
These examples show that %CONCATARR BiF is another useful addition to the RPG language.
You can learn more about the RPG %CONCATARR BiF from the IBM website here.
This article was written for IBM i 7.5 TR1 and 7.4 TR7.
Hi Simon,
ReplyDeleteAs always, a great post.
Two small typos though:-
"Line 2: I am defining an array where its elements are variable character, VARCHAR. The INZ keyword denotes that it will be a variable length array"
Should be "Line 2: I am defining an array where its elements are variable character, VARCHAR. The *auto keyword denotes that it will be a variable length array"
"These examples show that %CONSTARR BiF is another useful addition to the RPG language."
Should be "These examples show that %CONCATARR BiF is another useful addition to the RPG language.
Oops. Thank you for bringing those to my attention. I have made the corrections.
Delete