Wednesday, December 14, 2022

RPG concatenation BiF for arrays

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.

2 comments:

  1. Hi Simon,
    As 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.

    ReplyDelete
    Replies
    1. Oops. Thank you for bringing those to my attention. I have made the corrections.

      Delete

To prevent "comment spam" all comments are moderated.
Learn about this website's comments policy here.

Some people have reported that they cannot post a comment using certain computers and browsers. If this is you feel free to use the Contact Form to send me the comment and I will post it for you, please include the title of the post so I know which one to post the comment to.