Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# check if a string contains only number

I am trying to figure out a nice way to check if a string contains only number. This is the result of my effort but it seems really verbose:

let isDigit c = Char.IsDigit c

let rec strContainsOnlyNumber (s:string)=
    let charList = List.ofSeq s
    match charList with
        | x :: xs -> 
            if isDigit x then
                strContainsOnlyNumber ( String.Concat (Array.ofList xs))
            else 
                false
        | [] -> true

for example it seems really ugly that I have to convert a string to char list and then back to a string. Can you figure out a better solution?

like image 835
Zeta Avatar asked Feb 15 '17 15:02

Zeta


1 Answers

There are a few different options for approaching this.

Given that System.String is a sequence of characters, which you're currently using to turn into a list, you can skip the list conversions and just use Seq.forall to directly test:

let strContainsOnlyNumber (s:string) = s |> Seq.forall Char.IsDigit

If you want to see if it's a valid number, you can parse it into a number directly:

let strContainsOnlyNumber (s:string) = System.Int32.TryParse s |> fst

Note that this will also return true for things like "-342" (which contains -, but is a valid number).

Another approach would be to use a regular expression:

let numberCheck = System.Text.RegularExpressions.Regex("^[0-9]+$")    
let strContainsOnlyNumbers (s:string) = numberCheck.IsMatch s

This will also handle numeric characters, but could be adapted to include other symbols in numbers if needed.

If the goal is to later use the string as a number, my suggestion would be to just do a conversion, and store in an option:

let tryToInt s = 
    match System.Int32.TryParse s with
    | true, v -> Some v
    | false, _ -> None

This will allow you to check to see if the value was a number (via Option.isSome), pattern match to use the results, and more.

Note that conversions to floating point numbers is nearly identical - just change the Int32.TryParse to a Double.TryParse if you want to handle float values.

like image 145
Reed Copsey Avatar answered Dec 06 '22 23:12

Reed Copsey