is there a 'reverse' ENTRY function in ABL?

Posted by Rom Elwell on 23-Jun-2014 07:02

Forgive my ignorance, however with regards to the ENTRY function, it searches a list, left-to-right, for values based on an integer position and delimited by the specified delimiter.

Is there a function that will allow us to search a list in ‘reverse’ order, right-to-left?

ENTRY function
Returns a character string (CHARACTER or LONGCHAR) entry from a list based on an
integer position.
Syntax
element
An integer value that corresponds to the position of a character string in a list of values. If
the value of element does not correspond to an entry in the list, the AVM raises the
ERROR condition. If the value of element is the Unknown value (?), ENTRY returns the
Unknown value (?). If element is less than or equal to 0, or is larger than the number of
elements in list, ENTRY returns an error.
list
A list of character strings separated with a character delimiter. The list can be a variable
of type CHARACTER or LONGCHAR. If the value of list is the Unknown value (?),
ENTRY returns the Unknown value (?).
character
A delimiter you define for the list. The default is a comma. This allows the ENTRY
function to operate on non- comma-separated lists. If you use an alphabetic character, this
delimiter is case sensitive.

All Replies

Posted by James Palmer on 23-Jun-2014 07:09

There isn't a built in function, no.

Posted by James Palmer on 23-Jun-2014 07:11

Wait a minute.. Entry doesn't do what you think. ENTRY(10,lv-list) will give you the 10th entry. If you want to get each entry right to left then [code]

DO lv-i = NUM-ENTRIES(lv-list) TO 1 BY -1:

 message entry(lv-i.lv-list).

END. [/code]

Posted by Brian K. Maher on 23-Jun-2014 07:15

And if you want it to be faster for a larger list size since NUM-ENTRIES is calculated for each iteration do...
 
DEFINE VARIABLE iNumEntries AS INTEGER NO-UNDO.
ASSIGN iNumEntries = NUM-ENTRIES(lv-list).
 
DO lv-i = iNumEntries TO 1 BY -1:
    MESSAGE ENTRY(lv-i,lv-list).
END.
 

Posted by Dileep Dasa on 23-Jun-2014 07:20

I am still not sure of what you are trying to do but there is LOOKUP function which returns position of a character in the list specified. You can specify a delimiter of your choice to this function

LOOKUP ( expression , list [ , character ] )

Posted by Bill Wood on 23-Jun-2014 07:26

NUM-ENTRIES(list) and ENTRY(list,token) can be combined to get what you want (if I understand what you want)

DEF VAR list AS CHAR INITIAL "a,b,c,d,e". /* 5 entries */
DEF VAR entry2ndFromLeft AS CHAR.
DEF VAR entry2ndFromRight AS CHAR.
DEF VAR pos AS INTEGER INITIAL 2.

/* The 2nd ENTRY is easy going LEFT-to-RIGHT */
entry2ndFromLeft = ENTRY (pos, list).  /* 'b' */

/* To get 2nd from Right, just use NUM-ENTRIES and subtraction. */
entry2ndFromRight = ENTRY ( NUM-ENTRIES(list)+1-pos, list ).  /* 'd' */

(NOTE: code sample fixed based on feedback below :-) 

Posted by Dileep Dasa on 23-Jun-2014 07:42

Small change in [mention:cc09feab3621421d87a3c87b3a60d051:e9ed411860ed4f2ba0265705b8793d05]'s code (ENTRY function needs position as first argument and list as second argument):

DEF VAR list AS CHAR INITIAL "a,b,c,d,e". /* 5 entries */
DEF VAR entry2ndFromLeft AS CHAR.
DEF VAR entry2ndFromRight AS CHAR.
DEF VAR pos AS INTEGER INITIAL 2.
 
/* The 2nd ENTRY is easy going LEFT-to-RIGHT */
entry2ndFromLeft = ENTRY (pos, list).  /* 'b' */
 
/* To get 2nd from Right, just use NUM-ENTRIES and subtraction. */
entry2ndFromRight = ENTRY (NUM-ENTRIES(list) + 1 - pos, list).  /* 'd' */


Posted by jmls on 23-Jun-2014 07:48

or, converting the whole thing into a class using the power of ABL OO :

using Progress.Lang.*.

routine-level on error undo, throw.

class whoGloo.utils.string: 

  method static char R-ENTRY(p_pos as int,p_list as char  ):
    return R-ENTRY(p_pos,p_list,",":u).
  end method.
  
	method static char R-ENTRY(p_pos as int,p_list as char,p_delimiter as char  ):
	  if p_pos eq ? or p_list eq ? or p_delimiter eq ? then return ?.
	  
	  if p_pos le 0 or num-entries(p_list,p_delimiter) lt p_pos 
	     then undo, throw new Progress.Lang.AppError(substitute("entry &1 is outside the range of list &2",
	                                                            p_pos,
	                                                            p_list),560).

    return entry(num-entries(p_list) + 1 - p_pos,p_list).                                                       
	end method.

end class.


you can then do

using whoGloo.utils.string.

message string:R-ENTRY(3,"a,b,c,d") view-as alert-box.


Posted by Bill Wood on 23-Jun-2014 07:53

I fixed my code (thanks Dileep)...   and "Liking" the OOABL and whogloo reference :-)

Posted by Stefan Drissen on 24-Jun-2014 18:24

Only the TO part is calculated for each iteration to see if the end condition has been met. So there is nothing faster in this case.

FUNCTION doStart RETURNS INTEGER():
   MESSAGE "start" VIEW-AS ALERT-BOX.

   RETURN 1.

END FUNCTION.

FUNCTION doEnd RETURNS INTEGER():
   MESSAGE "end" VIEW-AS ALERT-BOX.

   RETURN 5.

END FUNCTION.

DEF VAR ii AS INT NO-UNDO.

DO  ii = doStart() TO doEnd():

END.


This thread is closed