Extract only numbers of a string

Posted by goo on 24-May-2019 12:02

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....

All Replies

Posted by Laura Stern on 24-May-2019 12:44

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.

Posted by David Abdala on 24-May-2019 13:16

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...

Posted by 2087 on 24-May-2019 13:20

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).

Posted by tpavlovic on 24-May-2019 13:29

Where is an Extension Method, you can't use that in Progresss.
public static System.Collections.Generic.IEnumerable<TSource> Where<TSource> (this System.Collections.Generic.IEnumerable<TSource> source, Func<TSource,bool> predicate);

Posted by jonathan.wilson on 24-May-2019 13:40

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.

Posted by goo on 24-May-2019 14:06

I was just curious about how to do it in .Net. Since it take some time before a message comes, I had to resolve it with walking the chars and do a lookup(char,’0,1,2,…..’) gt 0…

It worked, but did not learn that much
&#128522;
 

Posted by goo on 24-May-2019 14:08

Aaah, you are so right… I did a test if it was an integer, but that is not needed….
 

Posted by goo on 24-May-2019 14:08

Nice to know… I was just curious…
 
//Geir Otto
 

Posted by tbergman on 24-May-2019 17:16

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.

This thread is closed