Reputation: 11595
I am attempting to convert a file name like the following:
ten_of_clubs.png
to
10_of_clubs.png
However, I do not like my implementation:
let getFile (card: Card Option) =
let fileName =
match card with
| Some card -> (getUnionTypeName card.Face + "_of_" + getUnionTypeName card.Suit + ".png").ToLower()
| None -> ""
let delimitedName = fileName.Split '_'
let currentFace = delimitedName.[0]
let updatedFace =
match currentFace with
| "two" -> "2"
| "three" -> "3"
| "four" -> "4"
| "five" -> "5"
| "six" -> "6"
| "seven" -> "7"
| "eight" -> "8"
| "nine" -> "9"
| "ten" -> "10"
| _ -> currentFace
updatedFace + "_" + delimitedName.[1] + "_" + delimitedName.[2]
In F#, how can I just change the first element of a string without referencing all elements?
Example:
updatedFace + "_" + delimitedName.[1] + "_" + delimitedName.[2]
to
updatedFace + "_" + delimitedName.[1..]
Upvotes: 1
Views: 85
Reputation: 233135
There's no reason to first construct a formatted string, then split it, and finally create a new formatted string.
Assuming that your intent is to return the empty string in the None
case, you can do something like this:
let getFile card =
let digitize candidate =
match candidate with
| "Two" -> "2"
| "Three" -> "3"
| "Four" -> "4"
| "Five" -> "5"
| "Six" -> "6"
| "Seven" -> "7"
| "Eight" -> "8"
| "Nine" -> "9"
| "Ten" -> "10"
| _ -> candidate
match card with
| Some c ->
let face = c.Face |> string |> digitize
let suit = c.Suit |> string
sprintf "%s_of_%s.png" face suit
| None -> ""
Here, I've assumed that the Face
and Suit
types override ToString
instead of relying on a function called getUnionTypeName
that I don't know of. This enables you to use the built-in function string
(which simply calls ToString ()
).
Ad hoc tests:
> Some { Face = Ten; Suit = Clubs } |> getFile;;
val it : string = "10_of_Clubs.png"
> Some { Face = Jack; Suit = Clubs } |> getFile;;
val it : string = "Jack_of_Clubs.png"
> None |> getFile;;
val it : string = ""
That digitize
function looks like a candidate for a general-purpose function, and I wonder if the BCL doesn't already have something like that lying around in its Globalization namespace... Otherwise, I'm sure there are hundreds of NuGet packages out there that implement such functionality...
It turns out that there aren't hundreds of NuGet packages that already do this, so I created one, called Numsense. With it, you can simplify the getFile
function to this:
open Ploeh.Numsense
let getFile card =
let digitize candidate =
match Numeral.tryParseEnglish candidate with
| Some i -> string i
| None -> candidate
match card with
| Some c ->
let face = c.Face |> string |> digitize
let suit = c.Suit |> string
sprintf "%s_of_%s.png" face suit
| None -> ""
Upvotes: 3
Reputation: 2395
After splitting your string by _ you get an array of parts. Array is mutable Collection. You can change First by your function and then concatenate by _ again.
let parts = myString.Split [|'_'|]
parts.[0] <- toNumber parts.[0]
String.concat "_" parts
Upvotes: 2