11.7
What is the simplest and quickest way of extracting numbers of a string variable?
I found this:
return new String(input.Where(Char.IsDigit).ToArray());
But found it a bit diffecult to translate into Progress :-)
def var myString as char no-undo.
myString = 'this is a 1234 tekst'.
myNumber = CAST(BOX(myString),System.String).......
either that, or do a loop on the string checking numbers....
Of course in straight ABL, you convert a numeric string to a number using the INTEGER function, Here you have a string with a number in it so you have to use SUBSTRING. You can find where the number is if you need to by walking through the chars and checking the value using I think the HEX function. Why are you trying to use .Net to do this?. Because you can do it in one statement?
I don’t believe you can do that from the ABL. “Where” is not a string method. It seems to be a language construct. Similarly, Char only resolves to the successive character in the string because it is used within the Where.
I don't know whats the meaning of "simple" and "fastest" for you..
Usually numbers in a string are at the beginning of it, or after a space, so you can simplify the search by using ENTRY:
def var mchEntry as char no-undo.
def var minLE as integer no-undo
def var minInd as integer no-undo
def var minPos as integer no-undo.
minLE = NUM-ENTRIES(ipchString,' ').
DO minInd = 1 TO minLE:
mchEntry = ENTRY(minInd,ipchString,' ').
IF LOOKUP(SUBSTRING(mchEntry,1,1),'0,1,2,3,4,5,6,7,8,9') EQ 0 THEN
NEXT.
minPos = 2.
DO WHILE minPos LT LENGTH(mchEntry) AND LOOKUP(SUBSTRING(mchEntry,minPos,1),'0,1,2,3,4,5,6,7,8,9') GT 0:
minPos = minPos + 1.
END.
RETURN SUBSTRING(mchEntry,1,minPos). /* your number, assuming you just want the first number in the string*/
END.
RETURN ''. /* no numbers in the string */
It is "simple" to understand, and the "fastest" to write and use...
If you just want all the digits - even if spread through the string in can be done even more simply by a single loop from 1 to LENGTH of string.
Use SUBSTRING to get a single character .
Check if it is a digit by checking >="0" and <= "9" - if it is add to second string.
After loop vNumber = INTEGER(vString2).
public static System.Collections.Generic.IEnumerable<TSource> Where<TSource> (this System.Collections.Generic.IEnumerable<TSource> source, Func<TSource,bool> predicate);
Assuming only one number in string.. the following will work like some examples above.
DEF VAR i AS INT NO-UNDO INIT 1.
DEF VAR myNum AS CHAR NO-UNDO INIT "".
def var myString as char no-undo.
myString = 'this is a 1234 tekst'.
DO WHILE i <= LENGTH(myString):
IF INDEX( "0123456789", SUBSTRING(myString,i, 1)) <> 0
THEN myNum = myNum + SUBSTRING(myString,i, 1).
i = i + 1.
END.
MESSAGE myNum int(myNum) VIEW-AS ALERT-BOX.
Since you expressed interest in a .Net solution, you may want to play with this as a possibility
DEF VAR xx AS CHAR.
xx = "There are numbers in43434343this string: 40, 30, and 10.".
DEF VAR foo AS CHAR EXTENT.
foo = System.Text.RegularExpressions.Regex:Split(xx, "\D+").
MESSAGE foo[1] foo[2] foo[3]
VIEW-AS ALERT-BOX.