I need to pass a sum in as a string into the console e.g. "4 + 5" and parse and calculate it.
If you are sure that your string is a sequence of numbers seperated by '+'
and possibly white spaces, you can do something like this:
"4 + 5".Split '+' |> Seq.sumBy (int)
What does it do? .Split '+'
separates the string by the character +
and creates sequence of strings. In this example, the sequence would look like [|"4 "; " 5"|]
. The function Seq.sumBy
applies a given function to a each element of a sequence and sums up the result. We use the function (int)
to convert strings to numbers.
Be aware that this solution fails miserably if the string either contains a character other than +
, whitespace and digits or if a string without a digit is separated by +
(e.g. + 7 + 8
or 7 ++ 8
).
You might want to catch System.FormatException
. You'd end up with something like
let sumString (input:string) : int =
try
input.Split '+' |> Seq.sumBy (int)
with
| :? System.FormatException ->
print "This does not look like a sum. Let's just assume the result is zero."
0
This would just output 0
for any invalid formula. Another option to avoid the exception is throwing away all unwanted characters and empty strings:
let sumString (input:System.String) : int =
(input |> String.filter (fun c -> ['0'; '1'; '2'; '3'; '4'; '5'; '6'; '7'; '8'; '9'; '+'] |> List.contains c)).Split '+'
|> Seq.filter (((<) 0) << String.length)
|> Seq.sumBy (int)
What does this code do? String.filter
asks our anonymous function for every character whether it shall be considered. Our anonymous function checks whether the character is in a list of allowed characters. The result is a new string containing only digits and +
. We split this string by +
.
Before we pass our list of strings to Seq.sumBy (int)
, we filter our empty strings. This is done with Seq.filter
and a composition of functions: (<)
returns true
if the first parameter is less than the second one. We use currying to obtain (<) 0
, which checks whether the given integer is bigger than 0
. We compose this function with String.length
which maps a string to an integer telling its length.
After letting Seq.filter
play with this function, we pass the resulting list to Seq.sumBy (int)
as above.
This, however, might lead to quite surprising results for anything else than sums. "4 * 5 + 7"
would yield 52
.